s3:smbd: pass smbd_server_connection and a snumused function pointer to reload_services()
[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         uint32_t active_connections;
142 };
143
144 static struct notify_back_channel *back_channels;
145
146 /* Map generic permissions to printer object specific permissions */
147
148 const struct standard_mapping printer_std_mapping = {
149         PRINTER_READ,
150         PRINTER_WRITE,
151         PRINTER_EXECUTE,
152         PRINTER_ALL_ACCESS
153 };
154
155 /* Map generic permissions to print server object specific permissions */
156
157 const struct standard_mapping printserver_std_mapping = {
158         SERVER_READ,
159         SERVER_WRITE,
160         SERVER_EXECUTE,
161         SERVER_ALL_ACCESS
162 };
163
164 /* API table for Xcv Monitor functions */
165
166 struct xcv_api_table {
167         const char *name;
168         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
169 };
170
171 static void prune_printername_cache(void);
172
173 /********************************************************************
174  * Canonicalize servername.
175  ********************************************************************/
176
177 static const char *canon_servername(const char *servername)
178 {
179         const char *pservername = servername;
180         while (*pservername == '\\') {
181                 pservername++;
182         }
183         return pservername;
184 }
185
186 /* translate between internal status numbers and NT status numbers */
187 static int nt_printj_status(int v)
188 {
189         switch (v) {
190         case LPQ_QUEUED:
191                 return 0;
192         case LPQ_PAUSED:
193                 return JOB_STATUS_PAUSED;
194         case LPQ_SPOOLING:
195                 return JOB_STATUS_SPOOLING;
196         case LPQ_PRINTING:
197                 return JOB_STATUS_PRINTING;
198         case LPQ_ERROR:
199                 return JOB_STATUS_ERROR;
200         case LPQ_DELETING:
201                 return JOB_STATUS_DELETING;
202         case LPQ_OFFLINE:
203                 return JOB_STATUS_OFFLINE;
204         case LPQ_PAPEROUT:
205                 return JOB_STATUS_PAPEROUT;
206         case LPQ_PRINTED:
207                 return JOB_STATUS_PRINTED;
208         case LPQ_DELETED:
209                 return JOB_STATUS_DELETED;
210         case LPQ_BLOCKED:
211                 return JOB_STATUS_BLOCKED_DEVQ;
212         case LPQ_USER_INTERVENTION:
213                 return JOB_STATUS_USER_INTERVENTION;
214         }
215         return 0;
216 }
217
218 static int nt_printq_status(int v)
219 {
220         switch (v) {
221         case LPQ_PAUSED:
222                 return PRINTER_STATUS_PAUSED;
223         case LPQ_QUEUED:
224         case LPQ_SPOOLING:
225         case LPQ_PRINTING:
226                 return 0;
227         }
228         return 0;
229 }
230
231 /***************************************************************************
232  Disconnect from the client
233 ****************************************************************************/
234
235 static void srv_spoolss_replycloseprinter(int snum,
236                                           struct printer_handle *prn_hnd)
237 {
238         WERROR result;
239         NTSTATUS status;
240
241         /*
242          * Tell the specific printing tdb we no longer want messages for this printer
243          * by deregistering our PID.
244          */
245
246         if (!print_notify_deregister_pid(snum)) {
247                 DEBUG(0, ("Failed to register our pid for printer %s\n",
248                           lp_const_servicename(snum)));
249         }
250
251         /* weird if the test succeeds !!! */
252         if (prn_hnd->notify.cli_chan == NULL ||
253             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
254             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
255             prn_hnd->notify.cli_chan->active_connections == 0) {
256                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
257                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
258                 TALLOC_FREE(prn_hnd->notify.cli_chan);
259                 return;
260         }
261
262         status = dcerpc_spoolss_ReplyClosePrinter(
263                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
264                                         talloc_tos(),
265                                         &prn_hnd->notify.cli_hnd,
266                                         &result);
267         if (!NT_STATUS_IS_OK(status)) {
268                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
269                           nt_errstr(status)));
270                 result = ntstatus_to_werror(status);
271         } else if (!W_ERROR_IS_OK(result)) {
272                 DEBUG(0, ("reply_close_printer failed [%s].\n",
273                           win_errstr(result)));
274         }
275
276         /* if it's the last connection, deconnect the IPC$ share */
277         if (prn_hnd->notify.cli_chan->active_connections == 1) {
278
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
289         if (prn_hnd->notify.cli_chan) {
290                 prn_hnd->notify.cli_chan->active_connections--;
291                 prn_hnd->notify.cli_chan = NULL;
292         }
293 }
294
295 /****************************************************************************
296  Functions to free a printer entry datastruct.
297 ****************************************************************************/
298
299 static int printer_entry_destructor(struct printer_handle *Printer)
300 {
301         if (Printer->notify.cli_chan != NULL &&
302             Printer->notify.cli_chan->active_connections > 0) {
303                 int snum = -1;
304
305                 switch(Printer->printer_type) {
306                 case SPLHND_SERVER:
307                         srv_spoolss_replycloseprinter(snum, Printer);
308                         break;
309
310                 case SPLHND_PRINTER:
311                         snum = print_queue_snum(Printer->sharename);
312                         if (snum != -1) {
313                                 srv_spoolss_replycloseprinter(snum, Printer);
314                         }
315                         break;
316                 default:
317                         break;
318                 }
319         }
320
321         Printer->notify.flags=0;
322         Printer->notify.options=0;
323         Printer->notify.localmachine[0]='\0';
324         Printer->notify.printerlocal=0;
325         TALLOC_FREE(Printer->notify.option);
326         TALLOC_FREE(Printer->devmode);
327
328         /* Remove from the internal list. */
329         DLIST_REMOVE(printers_list, Printer);
330         return 0;
331 }
332
333 /****************************************************************************
334   find printer index by handle
335 ****************************************************************************/
336
337 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
338                                                         struct policy_handle *hnd)
339 {
340         struct printer_handle *find_printer = NULL;
341
342         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
343                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
344                 return NULL;
345         }
346
347         return find_printer;
348 }
349
350 /****************************************************************************
351  Close printer index by handle.
352 ****************************************************************************/
353
354 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
355 {
356         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
357
358         if (!Printer) {
359                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
360                         OUR_HANDLE(hnd)));
361                 return false;
362         }
363
364         close_policy_hnd(p, hnd);
365
366         return true;
367 }
368
369 /****************************************************************************
370  Delete a printer given a handle.
371 ****************************************************************************/
372
373 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
374                                   const char *sharename,
375                                   struct messaging_context *msg_ctx)
376 {
377         char *cmd = lp_deleteprinter_cmd();
378         char *command = NULL;
379         int ret;
380         bool is_print_op = false;
381
382         /* can't fail if we don't try */
383
384         if ( !*cmd )
385                 return WERR_OK;
386
387         command = talloc_asprintf(ctx,
388                         "%s \"%s\"",
389                         cmd, sharename);
390         if (!command) {
391                 return WERR_NOMEM;
392         }
393         if ( token )
394                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
395
396         DEBUG(10,("Running [%s]\n", command));
397
398         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
399
400         if ( is_print_op )
401                 become_root();
402
403         if ( (ret = smbrun(command, NULL)) == 0 ) {
404                 /* Tell everyone we updated smb.conf. */
405                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
406         }
407
408         if ( is_print_op )
409                 unbecome_root();
410
411         /********** END SePrintOperatorPrivlege BLOCK **********/
412
413         DEBUGADD(10,("returned [%d]\n", ret));
414
415         TALLOC_FREE(command);
416
417         if (ret != 0)
418                 return WERR_BADFID; /* What to return here? */
419
420         return WERR_OK;
421 }
422
423 /****************************************************************************
424  Delete a printer given a handle.
425 ****************************************************************************/
426
427 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
428 {
429         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
430         WERROR result;
431
432         if (!Printer) {
433                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
434                         OUR_HANDLE(hnd)));
435                 return WERR_BADFID;
436         }
437
438         /*
439          * It turns out that Windows allows delete printer on a handle
440          * opened by an admin user, then used on a pipe handle created
441          * by an anonymous user..... but they're working on security.... riiight !
442          * JRA.
443          */
444
445         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
446                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
447                 return WERR_ACCESS_DENIED;
448         }
449
450         /* this does not need a become root since the access check has been
451            done on the handle already */
452
453         result = winreg_delete_printer_key_internal(p->mem_ctx,
454                                            get_session_info_system(),
455                                            p->msg_ctx,
456                                            Printer->sharename,
457                                            "");
458         if (!W_ERROR_IS_OK(result)) {
459                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
460                 return WERR_BADFID;
461         }
462
463         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
464                                      Printer->sharename, p->msg_ctx);
465         if (!W_ERROR_IS_OK(result)) {
466                 return result;
467         }
468         prune_printername_cache();
469         return WERR_OK;
470 }
471
472 /****************************************************************************
473  Return the snum of a printer corresponding to an handle.
474 ****************************************************************************/
475
476 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
477                              int *number, struct share_params **params)
478 {
479         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
480
481         if (!Printer) {
482                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
483                         OUR_HANDLE(hnd)));
484                 return false;
485         }
486
487         switch (Printer->printer_type) {
488                 case SPLHND_PRINTER:
489                         DEBUG(4,("short name:%s\n", Printer->sharename));
490                         *number = print_queue_snum(Printer->sharename);
491                         return (*number != -1);
492                 case SPLHND_SERVER:
493                         return false;
494                 default:
495                         return false;
496         }
497 }
498
499 /****************************************************************************
500  Set printer handle type.
501  Check if it's \\server or \\server\printer
502 ****************************************************************************/
503
504 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
505 {
506         DEBUG(3,("Setting printer type=%s\n", handlename));
507
508         /* it's a print server */
509         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
510                 DEBUGADD(4,("Printer is a print server\n"));
511                 Printer->printer_type = SPLHND_SERVER;
512         }
513         /* it's a printer (set_printer_hnd_name() will handle port monitors */
514         else {
515                 DEBUGADD(4,("Printer is a printer\n"));
516                 Printer->printer_type = SPLHND_PRINTER;
517         }
518
519         return true;
520 }
521
522 static void prune_printername_cache_fn(const char *key, const char *value,
523                                        time_t timeout, void *private_data)
524 {
525         gencache_del(key);
526 }
527
528 static void prune_printername_cache(void)
529 {
530         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
531 }
532
533 /****************************************************************************
534  Set printer handle name..  Accept names like \\server, \\server\printer,
535  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
536  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
537  XcvDataPort() interface.
538 ****************************************************************************/
539
540 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
541                                    const struct auth_session_info *session_info,
542                                    struct messaging_context *msg_ctx,
543                                    struct printer_handle *Printer,
544                                    const char *handlename)
545 {
546         int snum;
547         int n_services=lp_numservices();
548         char *aprinter;
549         const char *printername;
550         const char *servername = NULL;
551         fstring sname;
552         bool found = false;
553         struct spoolss_PrinterInfo2 *info2 = NULL;
554         WERROR result;
555         char *p;
556
557         /*
558          * Hopefully nobody names his printers like this. Maybe \ or ,
559          * are illegal in printer names even?
560          */
561         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
562         char *cache_key;
563         char *tmp;
564
565         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
566                 (unsigned long)strlen(handlename)));
567
568         aprinter = discard_const_p(char, handlename);
569         if ( *handlename == '\\' ) {
570                 servername = canon_servername(handlename);
571                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
572                         *aprinter = '\0';
573                         aprinter++;
574                 }
575                 if (!is_myname_or_ipaddr(servername)) {
576                         return WERR_INVALID_PRINTER_NAME;
577                 }
578                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
579                 if (Printer->servername == NULL) {
580                         return WERR_NOMEM;
581                 }
582         }
583
584         if (Printer->printer_type == SPLHND_SERVER) {
585                 return WERR_OK;
586         }
587
588         if (Printer->printer_type != SPLHND_PRINTER) {
589                 return WERR_INVALID_HANDLE;
590         }
591
592         DEBUGADD(5, ("searching for [%s]\n", aprinter));
593
594         p = strchr(aprinter, ',');
595         if (p != NULL) {
596                 char *p2 = p;
597                 p++;
598                 if (*p == ' ') {
599                         p++;
600                 }
601                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
602                         *p2 = '\0';
603                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
604                         *p2 = '\0';
605                 }
606         }
607
608         if (p) {
609                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
610         }
611
612         /* check for the Port Monitor Interface */
613         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
614                 Printer->printer_type = SPLHND_PORTMON_TCP;
615                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
616                 found = true;
617         }
618         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
619                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
620                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
621                 found = true;
622         }
623
624         /*
625          * With hundreds of printers, the "for" loop iterating all
626          * shares can be quite expensive, as it is done on every
627          * OpenPrinter. The loop maps "aprinter" to "sname", the
628          * result of which we cache in gencache.
629          */
630
631         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
632                                     aprinter);
633         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
634
635                 found = (strcmp(tmp, printer_not_found) != 0);
636                 if (!found) {
637                         DEBUG(4, ("Printer %s not found\n", aprinter));
638                         SAFE_FREE(tmp);
639                         return WERR_INVALID_PRINTER_NAME;
640                 }
641                 fstrcpy(sname, tmp);
642                 SAFE_FREE(tmp);
643         }
644
645         /* Search all sharenames first as this is easier than pulling
646            the printer_info_2 off of disk. Don't use find_service() since
647            that calls out to map_username() */
648
649         /* do another loop to look for printernames */
650         for (snum = 0; !found && snum < n_services; snum++) {
651                 const char *printer = lp_const_servicename(snum);
652
653                 /* no point going on if this is not a printer */
654                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
655                         continue;
656                 }
657
658                 /* ignore [printers] share */
659                 if (strequal(printer, "printers")) {
660                         continue;
661                 }
662
663                 fstrcpy(sname, printer);
664                 if (strequal(aprinter, printer)) {
665                         found = true;
666                         break;
667                 }
668
669                 /* no point looking up the printer object if
670                    we aren't allowing printername != sharename */
671                 if (lp_force_printername(snum)) {
672                         continue;
673                 }
674
675                 result = winreg_get_printer_internal(mem_ctx,
676                                             session_info,
677                                             msg_ctx,
678                                             sname,
679                                             &info2);
680                 if ( !W_ERROR_IS_OK(result) ) {
681                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
682                                  sname, win_errstr(result)));
683                         continue;
684                 }
685
686                 printername = strrchr(info2->printername, '\\');
687                 if (printername == NULL) {
688                         printername = info2->printername;
689                 } else {
690                         printername++;
691                 }
692
693                 if (strequal(printername, aprinter)) {
694                         found = true;
695                         break;
696                 }
697
698                 DEBUGADD(10, ("printername: %s\n", printername));
699
700                 TALLOC_FREE(info2);
701         }
702
703         if ( !found ) {
704                 if (cache_key != NULL) {
705                         gencache_set(cache_key, printer_not_found,
706                                      time(NULL)+300);
707                         TALLOC_FREE(cache_key);
708                 }
709                 DEBUGADD(4,("Printer not found\n"));
710                 return WERR_INVALID_PRINTER_NAME;
711         }
712
713         if (cache_key != NULL) {
714                 gencache_set(cache_key, sname, time(NULL)+300);
715                 TALLOC_FREE(cache_key);
716         }
717
718         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
719
720         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
721
722         return WERR_OK;
723 }
724
725 /****************************************************************************
726  Find first available printer slot. creates a printer handle for you.
727  ****************************************************************************/
728
729 static WERROR open_printer_hnd(struct pipes_struct *p,
730                                struct policy_handle *hnd,
731                                const char *name,
732                                uint32_t access_granted)
733 {
734         struct printer_handle *new_printer;
735         WERROR result;
736
737         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
738
739         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
740         if (new_printer == NULL) {
741                 return WERR_NOMEM;
742         }
743         talloc_set_destructor(new_printer, printer_entry_destructor);
744
745         /* This also steals the printer_handle on the policy_handle */
746         if (!create_policy_hnd(p, hnd, new_printer)) {
747                 TALLOC_FREE(new_printer);
748                 return WERR_INVALID_HANDLE;
749         }
750
751         /* Add to the internal list. */
752         DLIST_ADD(printers_list, new_printer);
753
754         new_printer->notify.option=NULL;
755
756         if (!set_printer_hnd_printertype(new_printer, name)) {
757                 close_printer_handle(p, hnd);
758                 return WERR_INVALID_HANDLE;
759         }
760
761         result = set_printer_hnd_name(p->mem_ctx,
762                                       get_session_info_system(),
763                                       p->msg_ctx,
764                                       new_printer, name);
765         if (!W_ERROR_IS_OK(result)) {
766                 close_printer_handle(p, hnd);
767                 return result;
768         }
769
770         new_printer->access_granted = access_granted;
771
772         DEBUG(5, ("%d printer handles active\n",
773                   (int)num_pipe_handles(p)));
774
775         return WERR_OK;
776 }
777
778 /***************************************************************************
779  check to see if the client motify handle is monitoring the notification
780  given by (notify_type, notify_field).
781  **************************************************************************/
782
783 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
784                                       uint16_t notify_field)
785 {
786         return true;
787 }
788
789 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
790                                 uint16_t notify_field)
791 {
792         struct spoolss_NotifyOption *option = p->notify.option;
793         uint32_t i, j;
794
795         /*
796          * Flags should always be zero when the change notify
797          * is registered by the client's spooler.  A user Win32 app
798          * might use the flags though instead of the NOTIFY_OPTION_INFO
799          * --jerry
800          */
801
802         if (!option) {
803                 return false;
804         }
805
806         if (p->notify.flags)
807                 return is_monitoring_event_flags(
808                         p->notify.flags, notify_type, notify_field);
809
810         for (i = 0; i < option->count; i++) {
811
812                 /* Check match for notify_type */
813
814                 if (option->types[i].type != notify_type)
815                         continue;
816
817                 /* Check match for field */
818
819                 for (j = 0; j < option->types[i].count; j++) {
820                         if (option->types[i].fields[j].field == notify_field) {
821                                 return true;
822                         }
823                 }
824         }
825
826         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
827                    p->servername, p->sharename, notify_type, notify_field));
828
829         return false;
830 }
831
832 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
833         _data->data.integer[0] = _integer; \
834         _data->data.integer[1] = 0;
835
836
837 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
838         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
839         if (!_data->data.string.string) {\
840                 _data->data.string.size = 0; \
841         } \
842         _data->data.string.size = strlen_m_term(_p) * 2;
843
844 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
845         _data->data.devmode.devmode = _devmode;
846
847 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
848         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
849         if (!_data->data.sd.sd) { \
850                 _data->data.sd.sd_size = 0; \
851         } \
852         _data->data.sd.sd_size = \
853                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
854
855 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
856                                    struct tm *t,
857                                    const char **pp,
858                                    uint32_t *plen)
859 {
860         struct spoolss_Time st;
861         uint32_t len = 16;
862         char *p;
863
864         if (!init_systemtime(&st, t)) {
865                 return;
866         }
867
868         p = talloc_array(mem_ctx, char, len);
869         if (!p) {
870                 return;
871         }
872
873         /*
874          * Systemtime must be linearized as a set of UINT16's.
875          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
876          */
877
878         SSVAL(p, 0, st.year);
879         SSVAL(p, 2, st.month);
880         SSVAL(p, 4, st.day_of_week);
881         SSVAL(p, 6, st.day);
882         SSVAL(p, 8, st.hour);
883         SSVAL(p, 10, st.minute);
884         SSVAL(p, 12, st.second);
885         SSVAL(p, 14, st.millisecond);
886
887         *pp = p;
888         *plen = len;
889 }
890
891 /* Convert a notification message to a struct spoolss_Notify */
892
893 static void notify_one_value(struct spoolss_notify_msg *msg,
894                              struct spoolss_Notify *data,
895                              TALLOC_CTX *mem_ctx)
896 {
897         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
898 }
899
900 static void notify_string(struct spoolss_notify_msg *msg,
901                           struct spoolss_Notify *data,
902                           TALLOC_CTX *mem_ctx)
903 {
904         /* The length of the message includes the trailing \0 */
905
906         data->data.string.size = msg->len * 2;
907         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
908         if (!data->data.string.string) {
909                 data->data.string.size = 0;
910                 return;
911         }
912 }
913
914 static void notify_system_time(struct spoolss_notify_msg *msg,
915                                struct spoolss_Notify *data,
916                                TALLOC_CTX *mem_ctx)
917 {
918         data->data.string.string = NULL;
919         data->data.string.size = 0;
920
921         if (msg->len != sizeof(time_t)) {
922                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
923                           msg->len));
924                 return;
925         }
926
927         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
928                                &data->data.string.string,
929                                &data->data.string.size);
930 }
931
932 struct notify2_message_table {
933         const char *name;
934         void (*fn)(struct spoolss_notify_msg *msg,
935                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
936 };
937
938 static struct notify2_message_table printer_notify_table[] = {
939         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
940         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
941         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
942         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
943         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
944         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
945         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
946         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
947         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
948         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
949         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
950         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
951         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
952         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
953         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
954         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
955         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
956         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
957         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
958 };
959
960 static struct notify2_message_table job_notify_table[] = {
961         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
962         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
963         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
964         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
965         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
966         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
967         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
968         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
969         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
970         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
971         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
972         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
973         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
974         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
975         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
976         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
977         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
978         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
979         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
980         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
981         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
982         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
983         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
984         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
985 };
986
987
988 /***********************************************************************
989  Allocate talloc context for container object
990  **********************************************************************/
991
992 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
993 {
994         if ( !ctr )
995                 return;
996
997         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
998
999         return;
1000 }
1001
1002 /***********************************************************************
1003  release all allocated memory and zero out structure
1004  **********************************************************************/
1005
1006 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1007 {
1008         if ( !ctr )
1009                 return;
1010
1011         if ( ctr->ctx )
1012                 talloc_destroy(ctr->ctx);
1013
1014         ZERO_STRUCTP(ctr);
1015
1016         return;
1017 }
1018
1019 /***********************************************************************
1020  **********************************************************************/
1021
1022 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1023 {
1024         if ( !ctr )
1025                 return NULL;
1026
1027         return ctr->ctx;
1028 }
1029
1030 /***********************************************************************
1031  **********************************************************************/
1032
1033 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1034 {
1035         if ( !ctr || !ctr->msg_groups )
1036                 return NULL;
1037
1038         if ( idx >= ctr->num_groups )
1039                 return NULL;
1040
1041         return &ctr->msg_groups[idx];
1042
1043 }
1044
1045 /***********************************************************************
1046  How many groups of change messages do we have ?
1047  **********************************************************************/
1048
1049 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1050 {
1051         if ( !ctr )
1052                 return 0;
1053
1054         return ctr->num_groups;
1055 }
1056
1057 /***********************************************************************
1058  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1059  **********************************************************************/
1060
1061 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1062 {
1063         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1064         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1065         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1066         int                             i, new_slot;
1067
1068         if ( !ctr || !msg )
1069                 return 0;
1070
1071         /* loop over all groups looking for a matching printer name */
1072
1073         for ( i=0; i<ctr->num_groups; i++ ) {
1074                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1075                         break;
1076         }
1077
1078         /* add a new group? */
1079
1080         if ( i == ctr->num_groups ) {
1081                 ctr->num_groups++;
1082
1083                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1084                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1085                         return 0;
1086                 }
1087                 ctr->msg_groups = groups;
1088
1089                 /* clear the new entry and set the printer name */
1090
1091                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1092                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1093         }
1094
1095         /* add the change messages; 'i' is the correct index now regardless */
1096
1097         msg_grp = &ctr->msg_groups[i];
1098
1099         msg_grp->num_msgs++;
1100
1101         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1102                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1103                 return 0;
1104         }
1105         msg_grp->msgs = msg_list;
1106
1107         new_slot = msg_grp->num_msgs-1;
1108         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1109
1110         /* need to allocate own copy of data */
1111
1112         if ( msg->len != 0 )
1113                 msg_grp->msgs[new_slot].notify.data = (char *)
1114                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1115
1116         return ctr->num_groups;
1117 }
1118
1119 static void construct_info_data(struct spoolss_Notify *info_data,
1120                                 enum spoolss_NotifyType type,
1121                                 uint16_t field, int id);
1122
1123 /***********************************************************************
1124  Send a change notication message on all handles which have a call
1125  back registered
1126  **********************************************************************/
1127
1128 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1129                                   struct printer_handle *prn_hnd,
1130                                   SPOOLSS_NOTIFY_MSG *messages,
1131                                   uint32_t num_msgs,
1132                                   struct spoolss_Notify **_notifies,
1133                                   int *_count)
1134 {
1135         struct spoolss_Notify *notifies;
1136         SPOOLSS_NOTIFY_MSG *msg;
1137         int count = 0;
1138         uint32_t id;
1139         int i;
1140
1141         notifies = talloc_zero_array(mem_ctx,
1142                                      struct spoolss_Notify, num_msgs);
1143         if (!notifies) {
1144                 return ENOMEM;
1145         }
1146
1147         for (i = 0; i < num_msgs; i++) {
1148
1149                 msg = &messages[i];
1150
1151                 /* Are we monitoring this event? */
1152
1153                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1154                         continue;
1155                 }
1156
1157                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1158                            "for printer [%s]\n",
1159                            msg->type, msg->field, prn_hnd->sharename));
1160
1161                 /*
1162                  * if the is a printer notification handle and not a job
1163                  * notification type, then set the id to 0.
1164                  * Otherwise just use what was specified in the message.
1165                  *
1166                  * When registering change notification on a print server
1167                  * handle we always need to send back the id (snum) matching
1168                  * the printer for which the change took place.
1169                  * For change notify registered on a printer handle,
1170                  * this does not matter and the id should be 0.
1171                  *
1172                  * --jerry
1173                  */
1174
1175                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1176                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1177                         id = 0;
1178                 } else {
1179                         id = msg->id;
1180                 }
1181
1182                 /* Convert unix jobid to smb jobid */
1183
1184                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1185                         id = sysjob_to_jobid(msg->id);
1186
1187                         if (id == -1) {
1188                                 DEBUG(3, ("no such unix jobid %d\n",
1189                                           msg->id));
1190                                 continue;
1191                         }
1192                 }
1193
1194                 construct_info_data(&notifies[count],
1195                                     msg->type, msg->field, id);
1196
1197                 switch(msg->type) {
1198                 case PRINTER_NOTIFY_TYPE:
1199                         if (printer_notify_table[msg->field].fn) {
1200                                 printer_notify_table[msg->field].fn(msg,
1201                                                 &notifies[count], mem_ctx);
1202                         }
1203                         break;
1204
1205                 case JOB_NOTIFY_TYPE:
1206                         if (job_notify_table[msg->field].fn) {
1207                                 job_notify_table[msg->field].fn(msg,
1208                                                 &notifies[count], mem_ctx);
1209                         }
1210                         break;
1211
1212                 default:
1213                         DEBUG(5, ("Unknown notification type %d\n",
1214                                   msg->type));
1215                         continue;
1216                 }
1217
1218                 count++;
1219         }
1220
1221         *_notifies = notifies;
1222         *_count = count;
1223
1224         return 0;
1225 }
1226
1227 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1228                                 struct printer_handle *prn_hnd,
1229                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1230 {
1231         struct spoolss_Notify *notifies;
1232         int count = 0;
1233         union spoolss_ReplyPrinterInfo info;
1234         struct spoolss_NotifyInfo info0;
1235         uint32_t reply_result;
1236         NTSTATUS status;
1237         WERROR werr;
1238         int ret;
1239
1240         /* Is there notification on this handle? */
1241         if (prn_hnd->notify.cli_chan == NULL ||
1242             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1243             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1244             prn_hnd->notify.cli_chan->active_connections == 0) {
1245                 return 0;
1246         }
1247
1248         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1249                    prn_hnd->servername, prn_hnd->sharename));
1250
1251         /* For this printer? Print servers always receive notifications. */
1252         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1253             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1254                 return 0;
1255         }
1256
1257         DEBUG(10,("Our printer\n"));
1258
1259         /* build the array of change notifications */
1260         ret = build_notify2_messages(mem_ctx, prn_hnd,
1261                                      msg_group->msgs,
1262                                      msg_group->num_msgs,
1263                                      &notifies, &count);
1264         if (ret) {
1265                 return ret;
1266         }
1267
1268         info0.version   = 0x2;
1269         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1270         info0.count     = count;
1271         info0.notifies  = notifies;
1272
1273         info.info0 = &info0;
1274
1275         status = dcerpc_spoolss_RouterReplyPrinterEx(
1276                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1277                                 mem_ctx,
1278                                 &prn_hnd->notify.cli_hnd,
1279                                 prn_hnd->notify.change, /* color */
1280                                 prn_hnd->notify.flags,
1281                                 &reply_result,
1282                                 0, /* reply_type, must be 0 */
1283                                 info, &werr);
1284         if (!NT_STATUS_IS_OK(status)) {
1285                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1286                           "failed: %s\n",
1287                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1288                           nt_errstr(status)));
1289                 werr = ntstatus_to_werror(status);
1290         } else if (!W_ERROR_IS_OK(werr)) {
1291                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1292                           "failed: %s\n",
1293                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1294                           win_errstr(werr)));
1295         }
1296         switch (reply_result) {
1297         case 0:
1298                 break;
1299         case PRINTER_NOTIFY_INFO_DISCARDED:
1300         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1301         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1302                 break;
1303         default:
1304                 break;
1305         }
1306
1307         return 0;
1308 }
1309
1310 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1311 {
1312         struct printer_handle    *p;
1313         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1314         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1315         int ret;
1316
1317         if ( !msg_group ) {
1318                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1319                 return;
1320         }
1321
1322         if (!msg_group->msgs) {
1323                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1324                 return;
1325         }
1326
1327         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1328
1329         /* loop over all printers */
1330
1331         for (p = printers_list; p; p = p->next) {
1332                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1333                 if (ret) {
1334                         goto done;
1335                 }
1336         }
1337
1338 done:
1339         DEBUG(8,("send_notify2_changes: Exit...\n"));
1340         return;
1341 }
1342
1343 /***********************************************************************
1344  **********************************************************************/
1345
1346 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1347 {
1348
1349         uint32_t tv_sec, tv_usec;
1350         size_t offset = 0;
1351
1352         /* Unpack message */
1353
1354         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1355                              msg->printer);
1356
1357         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1358                                 &tv_sec, &tv_usec,
1359                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1360
1361         if (msg->len == 0)
1362                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1363                            &msg->notify.value[0], &msg->notify.value[1]);
1364         else
1365                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1366                            &msg->len, &msg->notify.data);
1367
1368         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1369                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1370
1371         tv->tv_sec = tv_sec;
1372         tv->tv_usec = tv_usec;
1373
1374         if (msg->len == 0)
1375                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1376                           msg->notify.value[1]));
1377         else
1378                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1379
1380         return true;
1381 }
1382
1383 /********************************************************************
1384  Receive a notify2 message list
1385  ********************************************************************/
1386
1387 static void receive_notify2_message_list(struct messaging_context *msg,
1388                                          void *private_data,
1389                                          uint32_t msg_type,
1390                                          struct server_id server_id,
1391                                          DATA_BLOB *data)
1392 {
1393         size_t                  msg_count, i;
1394         char                    *buf = (char *)data->data;
1395         char                    *msg_ptr;
1396         size_t                  msg_len;
1397         SPOOLSS_NOTIFY_MSG      notify;
1398         SPOOLSS_NOTIFY_MSG_CTR  messages;
1399         int                     num_groups;
1400
1401         if (data->length < 4) {
1402                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1403                 return;
1404         }
1405
1406         msg_count = IVAL(buf, 0);
1407         msg_ptr = buf + 4;
1408
1409         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1410
1411         if (msg_count == 0) {
1412                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1413                 return;
1414         }
1415
1416         /* initialize the container */
1417
1418         ZERO_STRUCT( messages );
1419         notify_msg_ctr_init( &messages );
1420
1421         /*
1422          * build message groups for each printer identified
1423          * in a change_notify msg.  Remember that a PCN message
1424          * includes the handle returned for the srv_spoolss_replyopenprinter()
1425          * call.  Therefore messages are grouped according to printer handle.
1426          */
1427
1428         for ( i=0; i<msg_count; i++ ) {
1429                 struct timeval msg_tv;
1430
1431                 if (msg_ptr + 4 - buf > data->length) {
1432                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1433                         return;
1434                 }
1435
1436                 msg_len = IVAL(msg_ptr,0);
1437                 msg_ptr += 4;
1438
1439                 if (msg_ptr + msg_len - buf > data->length) {
1440                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1441                         return;
1442                 }
1443
1444                 /* unpack messages */
1445
1446                 ZERO_STRUCT( notify );
1447                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1448                 msg_ptr += msg_len;
1449
1450                 /* add to correct list in container */
1451
1452                 notify_msg_ctr_addmsg( &messages, &notify );
1453
1454                 /* free memory that might have been allocated by notify2_unpack_msg() */
1455
1456                 if ( notify.len != 0 )
1457                         SAFE_FREE( notify.notify.data );
1458         }
1459
1460         /* process each group of messages */
1461
1462         num_groups = notify_msg_ctr_numgroups( &messages );
1463         for ( i=0; i<num_groups; i++ )
1464                 send_notify2_changes( &messages, i );
1465
1466
1467         /* cleanup */
1468
1469         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1470                 (uint32_t)msg_count ));
1471
1472         notify_msg_ctr_destroy( &messages );
1473
1474         return;
1475 }
1476
1477 /********************************************************************
1478  Send a message to ourself about new driver being installed
1479  so we can upgrade the information for each printer bound to this
1480  driver
1481  ********************************************************************/
1482
1483 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1484                                             struct messaging_context *msg_ctx)
1485 {
1486         int len = strlen(drivername);
1487
1488         if (!len)
1489                 return false;
1490
1491         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1492                 drivername));
1493
1494         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1495                            MSG_PRINTER_DRVUPGRADE,
1496                            (const uint8_t *)drivername, len+1);
1497
1498         return true;
1499 }
1500
1501 void srv_spoolss_cleanup(void)
1502 {
1503         struct printer_session_counter *session_counter;
1504
1505         for (session_counter = counter_list;
1506              session_counter != NULL;
1507              session_counter = counter_list) {
1508                 DLIST_REMOVE(counter_list, session_counter);
1509                 TALLOC_FREE(session_counter);
1510         }
1511 }
1512
1513 /**********************************************************************
1514  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1515  over all printers, upgrading ones as necessary
1516  **********************************************************************/
1517
1518 void do_drv_upgrade_printer(struct messaging_context *msg,
1519                             void *private_data,
1520                             uint32_t msg_type,
1521                             struct server_id server_id,
1522                             DATA_BLOB *data)
1523 {
1524         TALLOC_CTX *tmp_ctx;
1525         const struct auth_session_info *session_info = get_session_info_system();
1526         struct spoolss_PrinterInfo2 *pinfo2;
1527         WERROR result;
1528         const char *drivername;
1529         int snum;
1530         int n_services = lp_numservices();
1531         struct dcerpc_binding_handle *b = NULL;
1532
1533         tmp_ctx = talloc_new(NULL);
1534         if (!tmp_ctx) return;
1535
1536         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1537         if (!drivername) {
1538                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1539                 goto done;
1540         }
1541
1542         DEBUG(10, ("do_drv_upgrade_printer: "
1543                    "Got message for new driver [%s]\n", drivername));
1544
1545         /* Iterate the printer list */
1546
1547         for (snum = 0; snum < n_services; snum++) {
1548                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1549                         continue;
1550                 }
1551
1552                 /* ignore [printers] share */
1553                 if (strequal(lp_const_servicename(snum), "printers")) {
1554                         continue;
1555                 }
1556
1557                 if (b == NULL) {
1558                         result = winreg_printer_binding_handle(tmp_ctx,
1559                                                                session_info,
1560                                                                msg,
1561                                                                &b);
1562                         if (!W_ERROR_IS_OK(result)) {
1563                                 break;
1564                         }
1565                 }
1566
1567                 result = winreg_get_printer(tmp_ctx, b,
1568                                             lp_const_servicename(snum),
1569                                             &pinfo2);
1570
1571                 if (!W_ERROR_IS_OK(result)) {
1572                         continue;
1573                 }
1574
1575                 if (!pinfo2->drivername) {
1576                         continue;
1577                 }
1578
1579                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1580                         continue;
1581                 }
1582
1583                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1584
1585                 /* all we care about currently is the change_id */
1586                 result = winreg_printer_update_changeid(tmp_ctx, b,
1587                                                         pinfo2->printername);
1588
1589                 if (!W_ERROR_IS_OK(result)) {
1590                         DEBUG(3, ("do_drv_upgrade_printer: "
1591                                   "Failed to update changeid [%s]\n",
1592                                   win_errstr(result)));
1593                 }
1594         }
1595
1596         /* all done */
1597 done:
1598         talloc_free(tmp_ctx);
1599 }
1600
1601 /********************************************************************
1602  Update the cache for all printq's with a registered client
1603  connection
1604  ********************************************************************/
1605
1606 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1607 {
1608         struct printer_handle *printer = printers_list;
1609         int snum;
1610
1611         /* loop through all printers and update the cache where
1612            a client is connected */
1613         while (printer) {
1614                 if ((printer->printer_type == SPLHND_PRINTER) &&
1615                     ((printer->notify.cli_chan != NULL) &&
1616                      (printer->notify.cli_chan->active_connections > 0))) {
1617                         snum = print_queue_snum(printer->sharename);
1618                         print_queue_status(msg_ctx, snum, NULL, NULL);
1619                 }
1620
1621                 printer = printer->next;
1622         }
1623
1624         return;
1625 }
1626
1627 /****************************************************************
1628  _spoolss_OpenPrinter
1629 ****************************************************************/
1630
1631 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1632                             struct spoolss_OpenPrinter *r)
1633 {
1634         struct spoolss_OpenPrinterEx e;
1635         WERROR werr;
1636
1637         ZERO_STRUCT(e.in.userlevel);
1638
1639         e.in.printername        = r->in.printername;
1640         e.in.datatype           = r->in.datatype;
1641         e.in.devmode_ctr        = r->in.devmode_ctr;
1642         e.in.access_mask        = r->in.access_mask;
1643         e.in.level              = 0;
1644
1645         e.out.handle            = r->out.handle;
1646
1647         werr = _spoolss_OpenPrinterEx(p, &e);
1648
1649         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1650                 /* OpenPrinterEx returns this for a bad
1651                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1652                  * instead.
1653                  */
1654                 werr = WERR_INVALID_PRINTER_NAME;
1655         }
1656
1657         return werr;
1658 }
1659
1660 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1661                               struct spoolss_DeviceMode *orig,
1662                               struct spoolss_DeviceMode **dest)
1663 {
1664         struct spoolss_DeviceMode *dm;
1665
1666         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1667         if (!dm) {
1668                 return WERR_NOMEM;
1669         }
1670
1671         /* copy all values, then duplicate strings and structs */
1672         *dm = *orig;
1673
1674         dm->devicename = talloc_strdup(dm, orig->devicename);
1675         if (!dm->devicename) {
1676                 return WERR_NOMEM;
1677         }
1678         dm->formname = talloc_strdup(dm, orig->formname);
1679         if (!dm->formname) {
1680                 return WERR_NOMEM;
1681         }
1682         if (orig->driverextra_data.data) {
1683                 dm->driverextra_data.data =
1684                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1685                                         orig->driverextra_data.length);
1686                 if (!dm->driverextra_data.data) {
1687                         return WERR_NOMEM;
1688                 }
1689         }
1690
1691         *dest = dm;
1692         return WERR_OK;
1693 }
1694
1695 /****************************************************************
1696  _spoolss_OpenPrinterEx
1697 ****************************************************************/
1698
1699 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1700                               struct spoolss_OpenPrinterEx *r)
1701 {
1702         int snum;
1703         char *raddr;
1704         char *rhost;
1705         struct printer_handle *Printer=NULL;
1706         WERROR result;
1707         int rc;
1708
1709         if (!r->in.printername) {
1710                 return WERR_INVALID_PARAM;
1711         }
1712
1713         if (r->in.level > 3) {
1714                 return WERR_INVALID_PARAM;
1715         }
1716         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1717             (r->in.level == 2 && !r->in.userlevel.level2) ||
1718             (r->in.level == 3 && !r->in.userlevel.level3)) {
1719                 return WERR_INVALID_PARAM;
1720         }
1721
1722         /* some sanity check because you can open a printer or a print server */
1723         /* aka: \\server\printer or \\server */
1724
1725         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1726
1727         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1728         if (!W_ERROR_IS_OK(result)) {
1729                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1730                         "for printer %s\n", r->in.printername));
1731                 ZERO_STRUCTP(r->out.handle);
1732                 return result;
1733         }
1734
1735         Printer = find_printer_index_by_hnd(p, r->out.handle);
1736         if ( !Printer ) {
1737                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1738                         "handle we created for printer %s\n", r->in.printername));
1739                 close_printer_handle(p, r->out.handle);
1740                 ZERO_STRUCTP(r->out.handle);
1741                 return WERR_INVALID_PARAM;
1742         }
1743
1744         /*
1745          * First case: the user is opening the print server:
1746          *
1747          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1748          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1749          *
1750          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1751          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1752          * or if the user is listed in the smb.conf printer admin parameter.
1753          *
1754          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1755          * client view printer folder, but does not show the MSAPW.
1756          *
1757          * Note: this test needs code to check access rights here too. Jeremy
1758          * could you look at this?
1759          *
1760          * Second case: the user is opening a printer:
1761          * NT doesn't let us connect to a printer if the connecting user
1762          * doesn't have print permission.
1763          *
1764          * Third case: user is opening a Port Monitor
1765          * access checks same as opening a handle to the print server.
1766          */
1767
1768         switch (Printer->printer_type )
1769         {
1770         case SPLHND_SERVER:
1771         case SPLHND_PORTMON_TCP:
1772         case SPLHND_PORTMON_LOCAL:
1773                 /* Printserver handles use global struct... */
1774
1775                 snum = -1;
1776
1777                 /* Map standard access rights to object specific access rights */
1778
1779                 se_map_standard(&r->in.access_mask,
1780                                 &printserver_std_mapping);
1781
1782                 /* Deny any object specific bits that don't apply to print
1783                    servers (i.e printer and job specific bits) */
1784
1785                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1786
1787                 if (r->in.access_mask &
1788                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1789                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1790                         close_printer_handle(p, r->out.handle);
1791                         ZERO_STRUCTP(r->out.handle);
1792                         return WERR_ACCESS_DENIED;
1793                 }
1794
1795                 /* Allow admin access */
1796
1797                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1798                 {
1799                         if (!lp_ms_add_printer_wizard()) {
1800                                 close_printer_handle(p, r->out.handle);
1801                                 ZERO_STRUCTP(r->out.handle);
1802                                 return WERR_ACCESS_DENIED;
1803                         }
1804
1805                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1806                            and not a printer admin, then fail */
1807
1808                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1809                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1810                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1811                             !token_contains_name_in_list(
1812                                     uidtoname(p->session_info->unix_token->uid),
1813                                     p->session_info->info->domain_name,
1814                                     NULL,
1815                                     p->session_info->security_token,
1816                                     lp_printer_admin(snum))) {
1817                                 close_printer_handle(p, r->out.handle);
1818                                 ZERO_STRUCTP(r->out.handle);
1819                                 DEBUG(3,("access DENIED as user is not root, "
1820                                         "has no printoperator privilege, "
1821                                         "not a member of the printoperator builtin group and "
1822                                         "is not in printer admin list"));
1823                                 return WERR_ACCESS_DENIED;
1824                         }
1825
1826                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1827                 }
1828                 else
1829                 {
1830                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1831                 }
1832
1833                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1834                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1835
1836                 /* We fall through to return WERR_OK */
1837                 break;
1838
1839         case SPLHND_PRINTER:
1840                 /* NT doesn't let us connect to a printer if the connecting user
1841                    doesn't have print permission.  */
1842
1843                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1844                         close_printer_handle(p, r->out.handle);
1845                         ZERO_STRUCTP(r->out.handle);
1846                         return WERR_BADFID;
1847                 }
1848
1849                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1850                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1851                 }
1852
1853                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1854
1855                 /* map an empty access mask to the minimum access mask */
1856                 if (r->in.access_mask == 0x0)
1857                         r->in.access_mask = PRINTER_ACCESS_USE;
1858
1859                 /*
1860                  * If we are not serving the printer driver for this printer,
1861                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1862                  * will keep NT clients happy  --jerry
1863                  */
1864
1865                 if (lp_use_client_driver(snum)
1866                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1867                 {
1868                         r->in.access_mask = PRINTER_ACCESS_USE;
1869                 }
1870
1871                 /* check smb.conf parameters and the the sec_desc */
1872                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1873                                                          p->mem_ctx);
1874                 if (raddr == NULL) {
1875                         return WERR_NOMEM;
1876                 }
1877
1878                 rc = get_remote_hostname(p->remote_address,
1879                                          &rhost,
1880                                          p->mem_ctx);
1881                 if (rc < 0) {
1882                         return WERR_NOMEM;
1883                 }
1884                 if (strequal(rhost, "UNKNOWN")) {
1885                         rhost = raddr;
1886                 }
1887
1888                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1889                                   rhost, raddr)) {
1890                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1891                         ZERO_STRUCTP(r->out.handle);
1892                         return WERR_ACCESS_DENIED;
1893                 }
1894
1895                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1896                                    p->session_info->security_token, snum) ||
1897                     !print_access_check(p->session_info,
1898                                         p->msg_ctx,
1899                                         snum,
1900                                         r->in.access_mask)) {
1901                         DEBUG(3, ("access DENIED for printer open\n"));
1902                         close_printer_handle(p, r->out.handle);
1903                         ZERO_STRUCTP(r->out.handle);
1904                         return WERR_ACCESS_DENIED;
1905                 }
1906
1907                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1908                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1909                         close_printer_handle(p, r->out.handle);
1910                         ZERO_STRUCTP(r->out.handle);
1911                         return WERR_ACCESS_DENIED;
1912                 }
1913
1914                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1915                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1916                 else
1917                         r->in.access_mask = PRINTER_ACCESS_USE;
1918
1919                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1920                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1921
1922                 winreg_create_printer_internal(p->mem_ctx,
1923                                       get_session_info_system(),
1924                                       p->msg_ctx,
1925                                       lp_const_servicename(snum));
1926
1927                 break;
1928
1929         default:
1930                 /* sanity check to prevent programmer error */
1931                 ZERO_STRUCTP(r->out.handle);
1932                 return WERR_BADFID;
1933         }
1934
1935         Printer->access_granted = r->in.access_mask;
1936
1937         /*
1938          * If the client sent a devmode in the OpenPrinter() call, then
1939          * save it here in case we get a job submission on this handle
1940          */
1941
1942          if ((Printer->printer_type != SPLHND_SERVER) &&
1943              r->in.devmode_ctr.devmode) {
1944                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1945                                 &Printer->devmode);
1946          }
1947
1948 #if 0   /* JERRY -- I'm doubtful this is really effective */
1949         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1950            optimization in Windows 2000 clients  --jerry */
1951
1952         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1953                 && (RA_WIN2K == get_remote_arch()) )
1954         {
1955                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1956                 sys_usleep( 500000 );
1957         }
1958 #endif
1959
1960         return WERR_OK;
1961 }
1962
1963 /****************************************************************
1964  _spoolss_ClosePrinter
1965 ****************************************************************/
1966
1967 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1968                              struct spoolss_ClosePrinter *r)
1969 {
1970         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1971
1972         if (Printer && Printer->document_started) {
1973                 struct spoolss_EndDocPrinter e;
1974
1975                 e.in.handle = r->in.handle;
1976
1977                 _spoolss_EndDocPrinter(p, &e);
1978         }
1979
1980         if (!close_printer_handle(p, r->in.handle))
1981                 return WERR_BADFID;
1982
1983         /* clear the returned printer handle.  Observed behavior
1984            from Win2k server.  Don't think this really matters.
1985            Previous code just copied the value of the closed
1986            handle.    --jerry */
1987
1988         ZERO_STRUCTP(r->out.handle);
1989
1990         return WERR_OK;
1991 }
1992
1993 /****************************************************************
1994  _spoolss_DeletePrinter
1995 ****************************************************************/
1996
1997 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1998                               struct spoolss_DeletePrinter *r)
1999 {
2000         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2001         WERROR result;
2002         int snum;
2003
2004         if (Printer && Printer->document_started) {
2005                 struct spoolss_EndDocPrinter e;
2006
2007                 e.in.handle = r->in.handle;
2008
2009                 _spoolss_EndDocPrinter(p, &e);
2010         }
2011
2012         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2013                 winreg_delete_printer_key_internal(p->mem_ctx,
2014                                           get_session_info_system(),
2015                                           p->msg_ctx,
2016                                           lp_const_servicename(snum),
2017                                           "");
2018         }
2019
2020         result = delete_printer_handle(p, r->in.handle);
2021
2022         return result;
2023 }
2024
2025 /*******************************************************************
2026  * static function to lookup the version id corresponding to an
2027  * long architecture string
2028  ******************************************************************/
2029
2030 static const struct print_architecture_table_node archi_table[]= {
2031
2032         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2033         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2034         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2035         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2036         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2037         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2038         {"Windows x64",          SPL_ARCH_X64,          3 },
2039         {NULL,                   "",            -1 }
2040 };
2041
2042 static int get_version_id(const char *arch)
2043 {
2044         int i;
2045
2046         for (i=0; archi_table[i].long_archi != NULL; i++)
2047         {
2048                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2049                         return (archi_table[i].version);
2050         }
2051
2052         return -1;
2053 }
2054
2055 /****************************************************************
2056  _spoolss_DeletePrinterDriver
2057 ****************************************************************/
2058
2059 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2060                                     struct spoolss_DeletePrinterDriver *r)
2061 {
2062
2063         struct spoolss_DriverInfo8 *info = NULL;
2064         struct spoolss_DriverInfo8 *info_win2k = NULL;
2065         int                             version;
2066         WERROR                          status;
2067         struct dcerpc_binding_handle *b;
2068         TALLOC_CTX *tmp_ctx = NULL;
2069
2070         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2071            and not a printer admin, then fail */
2072
2073         if ( (p->session_info->unix_token->uid != sec_initial_uid())
2074              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2075                 && !token_contains_name_in_list(
2076                         uidtoname(p->session_info->unix_token->uid),
2077                         p->session_info->info->domain_name,
2078                         NULL,
2079                         p->session_info->security_token,
2080                         lp_printer_admin(-1)) )
2081         {
2082                 return WERR_ACCESS_DENIED;
2083         }
2084
2085         /* check that we have a valid driver name first */
2086
2087         if ((version = get_version_id(r->in.architecture)) == -1) {
2088                 return WERR_INVALID_ENVIRONMENT;
2089         }
2090
2091         tmp_ctx = talloc_new(p->mem_ctx);
2092         if (!tmp_ctx) {
2093                 return WERR_NOMEM;
2094         }
2095
2096         status = winreg_printer_binding_handle(tmp_ctx,
2097                                                get_session_info_system(),
2098                                                p->msg_ctx,
2099                                                &b);
2100         if (!W_ERROR_IS_OK(status)) {
2101                 goto done;
2102         }
2103
2104         status = winreg_get_driver(tmp_ctx, b,
2105                                    r->in.architecture, r->in.driver,
2106                                    version, &info);
2107         if (!W_ERROR_IS_OK(status)) {
2108                 /* try for Win2k driver if "Windows NT x86" */
2109
2110                 if ( version == 2 ) {
2111                         version = 3;
2112
2113                         status = winreg_get_driver(tmp_ctx, b,
2114                                                    r->in.architecture,
2115                                                    r->in.driver,
2116                                                    version, &info);
2117                         if (!W_ERROR_IS_OK(status)) {
2118                                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2119                                 goto done;
2120                         }
2121                 }
2122                 /* otherwise it was a failure */
2123                 else {
2124                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2125                         goto done;
2126                 }
2127
2128         }
2129
2130         if (printer_driver_in_use(tmp_ctx,
2131                                   b,
2132                                   info)) {
2133                 status = WERR_PRINTER_DRIVER_IN_USE;
2134                 goto done;
2135         }
2136
2137         if (version == 2) {
2138                 status = winreg_get_driver(tmp_ctx, b,
2139                                            r->in.architecture,
2140                                            r->in.driver, 3, &info_win2k);
2141                 if (W_ERROR_IS_OK(status)) {
2142                         /* if we get to here, we now have 2 driver info structures to remove */
2143                         /* remove the Win2k driver first*/
2144
2145                         status = winreg_del_driver(tmp_ctx, b,
2146                                                    info_win2k, 3);
2147                         talloc_free(info_win2k);
2148
2149                         /* this should not have failed---if it did, report to client */
2150                         if (!W_ERROR_IS_OK(status)) {
2151                                 goto done;
2152                         }
2153                 }
2154         }
2155
2156         status = winreg_del_driver(tmp_ctx, b,
2157                                    info, version);
2158
2159 done:
2160         talloc_free(tmp_ctx);
2161
2162         return status;
2163 }
2164
2165 /****************************************************************
2166  _spoolss_DeletePrinterDriverEx
2167 ****************************************************************/
2168
2169 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2170                                       struct spoolss_DeletePrinterDriverEx *r)
2171 {
2172         struct spoolss_DriverInfo8      *info = NULL;
2173         struct spoolss_DriverInfo8      *info_win2k = NULL;
2174         int                             version;
2175         bool                            delete_files;
2176         WERROR                          status;
2177         struct dcerpc_binding_handle *b;
2178         TALLOC_CTX *tmp_ctx = NULL;
2179
2180         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2181            and not a printer admin, then fail */
2182
2183         if ( (p->session_info->unix_token->uid != sec_initial_uid())
2184                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2185                 && !token_contains_name_in_list(
2186                         uidtoname(p->session_info->unix_token->uid),
2187                         p->session_info->info->domain_name,
2188                         NULL,
2189                         p->session_info->security_token, lp_printer_admin(-1)) )
2190         {
2191                 return WERR_ACCESS_DENIED;
2192         }
2193
2194         /* check that we have a valid driver name first */
2195         if ((version = get_version_id(r->in.architecture)) == -1) {
2196                 /* this is what NT returns */
2197                 return WERR_INVALID_ENVIRONMENT;
2198         }
2199
2200         if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) {
2201                 version = r->in.version;
2202         }
2203
2204         tmp_ctx = talloc_new(p->mem_ctx);
2205         if (!tmp_ctx) {
2206                 return WERR_NOMEM;
2207         }
2208
2209         status = winreg_printer_binding_handle(tmp_ctx,
2210                                                get_session_info_system(),
2211                                                p->msg_ctx,
2212                                                &b);
2213         if (!W_ERROR_IS_OK(status)) {
2214                 goto done;
2215         }
2216
2217         status = winreg_get_driver(tmp_ctx, b,
2218                                    r->in.architecture,
2219                                    r->in.driver,
2220                                    version,
2221                                    &info);
2222         if (!W_ERROR_IS_OK(status)) {
2223                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2224
2225                 /*
2226                  * if the client asked for a specific version,
2227                  * or this is something other than Windows NT x86,
2228                  * then we've failed
2229                  */
2230
2231                 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2232                         goto done;
2233
2234                 /* try for Win2k driver if "Windows NT x86" */
2235
2236                 version = 3;
2237                 status = winreg_get_driver(tmp_ctx, b,
2238                                            r->in.architecture,
2239                                            r->in.driver,
2240                                            version, &info);
2241                 if (!W_ERROR_IS_OK(status)) {
2242                         status = WERR_UNKNOWN_PRINTER_DRIVER;
2243                         goto done;
2244                 }
2245         }
2246
2247         if (printer_driver_in_use(tmp_ctx,
2248                                   b,
2249                                   info)) {
2250                 status = WERR_PRINTER_DRIVER_IN_USE;
2251                 goto done;
2252         }
2253
2254         /*
2255          * we have a couple of cases to consider.
2256          * (1) Are any files in use?  If so and DPD_DELTE_ALL_FILE is set,
2257          *     then the delete should fail if **any** files overlap with
2258          *     other drivers
2259          * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2260          *     non-overlapping files
2261          * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2262          *     is set, the do not delete any files
2263          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2264          */
2265
2266         delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2267
2268         /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2269
2270         if (delete_files &&
2271             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2272             printer_driver_files_in_use(tmp_ctx,
2273                                         b,
2274                                         info)) {
2275                 /* no idea of the correct error here */
2276                 status = WERR_ACCESS_DENIED;
2277                 goto done;
2278         }
2279
2280
2281         /* also check for W32X86/3 if necessary; maybe we already have? */
2282
2283         if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
2284                 status = winreg_get_driver(tmp_ctx, b,
2285                                            r->in.architecture,
2286                                            r->in.driver, 3, &info_win2k);
2287                 if (W_ERROR_IS_OK(status)) {
2288
2289                         if (delete_files &&
2290                             (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2291                             printer_driver_files_in_use(info,
2292                                                         b,
2293                                                         info_win2k)) {
2294                                 /* no idea of the correct error here */
2295                                 talloc_free(info_win2k);
2296                                 status = WERR_ACCESS_DENIED;
2297                                 goto done;
2298                         }
2299
2300                         /* if we get to here, we now have 2 driver info structures to remove */
2301                         /* remove the Win2k driver first*/
2302
2303                         status = winreg_del_driver(tmp_ctx, b,
2304                                                    info_win2k,
2305                                                    3);
2306
2307                         /* this should not have failed---if it did, report to client */
2308
2309                         if (!W_ERROR_IS_OK(status)) {
2310                                 goto done;
2311                         }
2312
2313                         /*
2314                          * now delete any associated files if delete_files is
2315                          * true. Even if this part failes, we return succes
2316                          * because the driver doesn not exist any more
2317                          */
2318                         if (delete_files) {
2319                                 delete_driver_files(get_session_info_system(),
2320                                                     info_win2k);
2321                         }
2322                 }
2323         }
2324
2325         status = winreg_del_driver(tmp_ctx, b,
2326                                    info,
2327                                    version);
2328         if (!W_ERROR_IS_OK(status)) {
2329                 goto done;
2330         }
2331
2332         /*
2333          * now delete any associated files if delete_files is
2334          * true. Even if this part failes, we return succes
2335          * because the driver doesn not exist any more
2336          */
2337         if (delete_files) {
2338                 delete_driver_files(get_session_info_system(), info);
2339         }
2340
2341 done:
2342         talloc_free(tmp_ctx);
2343         return status;
2344 }
2345
2346
2347 /********************************************************************
2348  GetPrinterData on a printer server Handle.
2349 ********************************************************************/
2350
2351 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2352                                             const char *value,
2353                                             enum winreg_Type *type,
2354                                             union spoolss_PrinterData *data)
2355 {
2356         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2357
2358         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2359                 *type = REG_DWORD;
2360                 data->value = 0x00;
2361                 return WERR_OK;
2362         }
2363
2364         if (!strcasecmp_m(value, "BeepEnabled")) {
2365                 *type = REG_DWORD;
2366                 data->value = 0x00;
2367                 return WERR_OK;
2368         }
2369
2370         if (!strcasecmp_m(value, "EventLog")) {
2371                 *type = REG_DWORD;
2372                 /* formally was 0x1b */
2373                 data->value = 0x00;
2374                 return WERR_OK;
2375         }
2376
2377         if (!strcasecmp_m(value, "NetPopup")) {
2378                 *type = REG_DWORD;
2379                 data->value = 0x00;
2380                 return WERR_OK;
2381         }
2382
2383         if (!strcasecmp_m(value, "MajorVersion")) {
2384                 *type = REG_DWORD;
2385
2386                 /* Windows NT 4.0 seems to not allow uploading of drivers
2387                    to a server that reports 0x3 as the MajorVersion.
2388                    need to investigate more how Win2k gets around this .
2389                    -- jerry */
2390
2391                 if (RA_WINNT == get_remote_arch()) {
2392                         data->value = 0x02;
2393                 } else {
2394                         data->value = 0x03;
2395                 }
2396
2397                 return WERR_OK;
2398         }
2399
2400         if (!strcasecmp_m(value, "MinorVersion")) {
2401                 *type = REG_DWORD;
2402                 data->value = 0x00;
2403                 return WERR_OK;
2404         }
2405
2406         /* REG_BINARY
2407          *  uint32_t size        = 0x114
2408          *  uint32_t major       = 5
2409          *  uint32_t minor       = [0|1]
2410          *  uint32_t build       = [2195|2600]
2411          *  extra unicode string = e.g. "Service Pack 3"
2412          */
2413         if (!strcasecmp_m(value, "OSVersion")) {
2414                 DATA_BLOB blob;
2415                 enum ndr_err_code ndr_err;
2416                 struct spoolss_OSVersion os;
2417
2418                 os.major                = 5;    /* Windows 2000 == 5.0 */
2419                 os.minor                = 0;
2420                 os.build                = 2195; /* build */
2421                 os.extra_string         = "";   /* leave extra string empty */
2422
2423                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2424                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2425                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2426                         return WERR_GENERAL_FAILURE;
2427                 }
2428
2429                 *type = REG_BINARY;
2430                 data->binary = blob;
2431
2432                 return WERR_OK;
2433         }
2434
2435
2436         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2437                 *type = REG_SZ;
2438
2439                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2440                 W_ERROR_HAVE_NO_MEMORY(data->string);
2441
2442                 return WERR_OK;
2443         }
2444
2445         if (!strcasecmp_m(value, "Architecture")) {
2446                 *type = REG_SZ;
2447                 data->string = talloc_strdup(mem_ctx,
2448                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2449                 W_ERROR_HAVE_NO_MEMORY(data->string);
2450
2451                 return WERR_OK;
2452         }
2453
2454         if (!strcasecmp_m(value, "DsPresent")) {
2455                 *type = REG_DWORD;
2456
2457                 /* only show the publish check box if we are a
2458                    member of a AD domain */
2459
2460                 if (lp_security() == SEC_ADS) {
2461                         data->value = 0x01;
2462                 } else {
2463                         data->value = 0x00;
2464                 }
2465                 return WERR_OK;
2466         }
2467
2468         if (!strcasecmp_m(value, "DNSMachineName")) {
2469                 const char *hostname = get_mydnsfullname();
2470
2471                 if (!hostname) {
2472                         return WERR_BADFILE;
2473                 }
2474
2475                 *type = REG_SZ;
2476                 data->string = talloc_strdup(mem_ctx, hostname);
2477                 W_ERROR_HAVE_NO_MEMORY(data->string);
2478
2479                 return WERR_OK;
2480         }
2481
2482         *type = REG_NONE;
2483
2484         return WERR_INVALID_PARAM;
2485 }
2486
2487 /****************************************************************
2488  _spoolss_GetPrinterData
2489 ****************************************************************/
2490
2491 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2492                                struct spoolss_GetPrinterData *r)
2493 {
2494         struct spoolss_GetPrinterDataEx r2;
2495
2496         r2.in.handle            = r->in.handle;
2497         r2.in.key_name          = "PrinterDriverData";
2498         r2.in.value_name        = r->in.value_name;
2499         r2.in.offered           = r->in.offered;
2500         r2.out.type             = r->out.type;
2501         r2.out.data             = r->out.data;
2502         r2.out.needed           = r->out.needed;
2503
2504         return _spoolss_GetPrinterDataEx(p, &r2);
2505 }
2506
2507 /*********************************************************
2508  Connect to the client machine.
2509 **********************************************************/
2510
2511 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2512                         struct sockaddr_storage *client_ss, const char *remote_machine)
2513 {
2514         NTSTATUS ret;
2515         struct cli_state *the_cli;
2516         struct sockaddr_storage rm_addr;
2517         char addr[INET6_ADDRSTRLEN];
2518
2519         if ( is_zero_addr(client_ss) ) {
2520                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2521                         remote_machine));
2522                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2523                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2524                         return false;
2525                 }
2526                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2527         } else {
2528                 rm_addr = *client_ss;
2529                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2530                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2531                         addr));
2532         }
2533
2534         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2535                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2536                         addr));
2537                 return false;
2538         }
2539
2540         /* setup the connection */
2541         ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2542                 &rm_addr, 0, "IPC$", "IPC",
2543                 "", /* username */
2544                 "", /* domain */
2545                 "", /* password */
2546                 0, lp_client_signing());
2547
2548         if ( !NT_STATUS_IS_OK( ret ) ) {
2549                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2550                         remote_machine ));
2551                 return false;
2552         }
2553
2554         if ( cli_state_protocol(the_cli) != PROTOCOL_NT1 ) {
2555                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2556                 cli_shutdown(the_cli);
2557                 return false;
2558         }
2559
2560         /*
2561          * Ok - we have an anonymous connection to the IPC$ share.
2562          * Now start the NT Domain stuff :-).
2563          */
2564
2565         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2566         if (!NT_STATUS_IS_OK(ret)) {
2567                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2568                         remote_machine, nt_errstr(ret)));
2569                 cli_shutdown(the_cli);
2570                 return false;
2571         }
2572
2573         return true;
2574 }
2575
2576 /***************************************************************************
2577  Connect to the client.
2578 ****************************************************************************/
2579
2580 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2581                                         uint32_t localprinter,
2582                                         enum winreg_Type type,
2583                                         struct policy_handle *handle,
2584                                         struct notify_back_channel **_chan,
2585                                         struct sockaddr_storage *client_ss,
2586                                         struct messaging_context *msg_ctx)
2587 {
2588         WERROR result;
2589         NTSTATUS status;
2590         struct notify_back_channel *chan;
2591
2592         for (chan = back_channels; chan; chan = chan->next) {
2593                 if (memcmp(&chan->client_address, client_ss,
2594                            sizeof(struct sockaddr_storage)) == 0) {
2595                         break;
2596                 }
2597         }
2598
2599         /*
2600          * If it's the first connection, contact the client
2601          * and connect to the IPC$ share anonymously
2602          */
2603         if (!chan) {
2604                 fstring unix_printer;
2605
2606                 /* the +2 is to strip the leading 2 backslashs */
2607                 fstrcpy(unix_printer, printer + 2);
2608
2609                 chan = talloc_zero(NULL, struct notify_back_channel);
2610                 if (!chan) {
2611                         return false;
2612                 }
2613                 chan->client_address = *client_ss;
2614
2615                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2616                         TALLOC_FREE(chan);
2617                         return false;
2618                 }
2619
2620                 DLIST_ADD(back_channels, chan);
2621
2622                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2623                                    receive_notify2_message_list);
2624         }
2625
2626         if (chan->cli_pipe == NULL ||
2627             chan->cli_pipe->binding_handle == NULL) {
2628                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2629                         "NULL %s for printer %s\n",
2630                         chan->cli_pipe == NULL ?
2631                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2632                         printer));
2633                 return false;
2634         }
2635
2636         /*
2637          * Tell the specific printing tdb we want messages for this printer
2638          * by registering our PID.
2639          */
2640
2641         if (!print_notify_register_pid(snum)) {
2642                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2643                           printer));
2644         }
2645
2646         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2647                                                  talloc_tos(),
2648                                                  printer,
2649                                                  localprinter,
2650                                                  type,
2651                                                  0,
2652                                                  NULL,
2653                                                  handle,
2654                                                  &result);
2655         if (!NT_STATUS_IS_OK(status)) {
2656                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2657                 result = ntstatus_to_werror(status);
2658         } else if (!W_ERROR_IS_OK(result)) {
2659                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2660         }
2661
2662         chan->active_connections++;
2663         *_chan = chan;
2664
2665         return (W_ERROR_IS_OK(result));
2666 }
2667
2668 /****************************************************************
2669  ****************************************************************/
2670
2671 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2672                                                              const struct spoolss_NotifyOption *r)
2673 {
2674         struct spoolss_NotifyOption *option;
2675         uint32_t i,k;
2676
2677         if (!r) {
2678                 return NULL;
2679         }
2680
2681         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2682         if (!option) {
2683                 return NULL;
2684         }
2685
2686         *option = *r;
2687
2688         if (!option->count) {
2689                 return option;
2690         }
2691
2692         option->types = talloc_zero_array(option,
2693                 struct spoolss_NotifyOptionType, option->count);
2694         if (!option->types) {
2695                 talloc_free(option);
2696                 return NULL;
2697         }
2698
2699         for (i=0; i < option->count; i++) {
2700                 option->types[i] = r->types[i];
2701
2702                 if (option->types[i].count) {
2703                         option->types[i].fields = talloc_zero_array(option,
2704                                 union spoolss_Field, option->types[i].count);
2705                         if (!option->types[i].fields) {
2706                                 talloc_free(option);
2707                                 return NULL;
2708                         }
2709                         for (k=0; k<option->types[i].count; k++) {
2710                                 option->types[i].fields[k] =
2711                                         r->types[i].fields[k];
2712                         }
2713                 }
2714         }
2715
2716         return option;
2717 }
2718
2719 /****************************************************************
2720  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2721  *
2722  * before replying OK: status=0 a rpc call is made to the workstation
2723  * asking ReplyOpenPrinter
2724  *
2725  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2726  * called from api_spoolss_rffpcnex
2727 ****************************************************************/
2728
2729 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2730                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2731 {
2732         int snum = -1;
2733         struct spoolss_NotifyOption *option = r->in.notify_options;
2734         struct sockaddr_storage client_ss;
2735         socklen_t client_len;
2736
2737         /* store the notify value in the printer struct */
2738
2739         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2740
2741         if (!Printer) {
2742                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2743                         "Invalid handle (%s:%u:%u).\n",
2744                         OUR_HANDLE(r->in.handle)));
2745                 return WERR_BADFID;
2746         }
2747
2748         Printer->notify.flags           = r->in.flags;
2749         Printer->notify.options         = r->in.options;
2750         Printer->notify.printerlocal    = r->in.printer_local;
2751         Printer->notify.msg_ctx         = p->msg_ctx;
2752
2753         TALLOC_FREE(Printer->notify.option);
2754         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2755
2756         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2757
2758         /* Connect to the client machine and send a ReplyOpenPrinter */
2759
2760         if ( Printer->printer_type == SPLHND_SERVER)
2761                 snum = -1;
2762         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2763                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2764                 return WERR_BADFID;
2765
2766         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2767                   "remote_address is %s\n",
2768                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2769
2770         if (!lp_print_notify_backchannel(snum)) {
2771                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2772                         "backchannel disabled\n"));
2773                 return WERR_SERVER_UNAVAILABLE;
2774         }
2775
2776         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2777                                                   (struct sockaddr *) &client_ss,
2778                                                   sizeof(struct sockaddr_storage));
2779         if (client_len < 0) {
2780                 return WERR_NOMEM;
2781         }
2782
2783         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2784                                         Printer->notify.printerlocal, REG_SZ,
2785                                         &Printer->notify.cli_hnd,
2786                                         &Printer->notify.cli_chan,
2787                                         &client_ss, p->msg_ctx)) {
2788                 return WERR_SERVER_UNAVAILABLE;
2789         }
2790
2791         return WERR_OK;
2792 }
2793
2794 /*******************************************************************
2795  * fill a notify_info_data with the servername
2796  ********************************************************************/
2797
2798 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2799                                        int snum,
2800                                        struct spoolss_Notify *data,
2801                                        print_queue_struct *queue,
2802                                        struct spoolss_PrinterInfo2 *pinfo2,
2803                                        TALLOC_CTX *mem_ctx)
2804 {
2805         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2806 }
2807
2808 /*******************************************************************
2809  * fill a notify_info_data with the printername (not including the servername).
2810  ********************************************************************/
2811
2812 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2813                                         int snum,
2814                                         struct spoolss_Notify *data,
2815                                         print_queue_struct *queue,
2816                                         struct spoolss_PrinterInfo2 *pinfo2,
2817                                         TALLOC_CTX *mem_ctx)
2818 {
2819         /* the notify name should not contain the \\server\ part */
2820         const char *p = strrchr(pinfo2->printername, '\\');
2821
2822         if (!p) {
2823                 p = pinfo2->printername;
2824         } else {
2825                 p++;
2826         }
2827
2828         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2829 }
2830
2831 /*******************************************************************
2832  * fill a notify_info_data with the servicename
2833  ********************************************************************/
2834
2835 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2836                                       int snum,
2837                                       struct spoolss_Notify *data,
2838                                       print_queue_struct *queue,
2839                                       struct spoolss_PrinterInfo2 *pinfo2,
2840                                       TALLOC_CTX *mem_ctx)
2841 {
2842         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2843 }
2844
2845 /*******************************************************************
2846  * fill a notify_info_data with the port name
2847  ********************************************************************/
2848
2849 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2850                                      int snum,
2851                                      struct spoolss_Notify *data,
2852                                      print_queue_struct *queue,
2853                                      struct spoolss_PrinterInfo2 *pinfo2,
2854                                      TALLOC_CTX *mem_ctx)
2855 {
2856         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2857 }
2858
2859 /*******************************************************************
2860  * fill a notify_info_data with the printername
2861  * but it doesn't exist, have to see what to do
2862  ********************************************************************/
2863
2864 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2865                                        int snum,
2866                                        struct spoolss_Notify *data,
2867                                        print_queue_struct *queue,
2868                                        struct spoolss_PrinterInfo2 *pinfo2,
2869                                        TALLOC_CTX *mem_ctx)
2870 {
2871         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2872 }
2873
2874 /*******************************************************************
2875  * fill a notify_info_data with the comment
2876  ********************************************************************/
2877
2878 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2879                                    int snum,
2880                                    struct spoolss_Notify *data,
2881                                    print_queue_struct *queue,
2882                                    struct spoolss_PrinterInfo2 *pinfo2,
2883                                    TALLOC_CTX *mem_ctx)
2884 {
2885         const char *p;
2886
2887         if (*pinfo2->comment == '\0') {
2888                 p = lp_comment(snum);
2889         } else {
2890                 p = pinfo2->comment;
2891         }
2892
2893         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2894 }
2895
2896 /*******************************************************************
2897  * fill a notify_info_data with the comment
2898  * location = "Room 1, floor 2, building 3"
2899  ********************************************************************/
2900
2901 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2902                                     int snum,
2903                                     struct spoolss_Notify *data,
2904                                     print_queue_struct *queue,
2905                                     struct spoolss_PrinterInfo2 *pinfo2,
2906                                     TALLOC_CTX *mem_ctx)
2907 {
2908         const char *loc = pinfo2->location;
2909         NTSTATUS status;
2910
2911         status = printer_list_get_printer(mem_ctx,
2912                                           pinfo2->sharename,
2913                                           NULL,
2914                                           &loc,
2915                                           NULL);
2916         if (NT_STATUS_IS_OK(status)) {
2917                 if (loc == NULL) {
2918                         loc = pinfo2->location;
2919                 }
2920         }
2921
2922         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2923 }
2924
2925 /*******************************************************************
2926  * fill a notify_info_data with the device mode
2927  * jfm:xxxx don't to it for know but that's a real problem !!!
2928  ********************************************************************/
2929
2930 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2931                                    int snum,
2932                                    struct spoolss_Notify *data,
2933                                    print_queue_struct *queue,
2934                                    struct spoolss_PrinterInfo2 *pinfo2,
2935                                    TALLOC_CTX *mem_ctx)
2936 {
2937         /* for a dummy implementation we have to zero the fields */
2938         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2939 }
2940
2941 /*******************************************************************
2942  * fill a notify_info_data with the separator file name
2943  ********************************************************************/
2944
2945 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2946                                    int snum,
2947                                    struct spoolss_Notify *data,
2948                                    print_queue_struct *queue,
2949                                    struct spoolss_PrinterInfo2 *pinfo2,
2950                                    TALLOC_CTX *mem_ctx)
2951 {
2952         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2953 }
2954
2955 /*******************************************************************
2956  * fill a notify_info_data with the print processor
2957  * jfm:xxxx return always winprint to indicate we don't do anything to it
2958  ********************************************************************/
2959
2960 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2961                                            int snum,
2962                                            struct spoolss_Notify *data,
2963                                            print_queue_struct *queue,
2964                                            struct spoolss_PrinterInfo2 *pinfo2,
2965                                            TALLOC_CTX *mem_ctx)
2966 {
2967         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2968 }
2969
2970 /*******************************************************************
2971  * fill a notify_info_data with the print processor options
2972  * jfm:xxxx send an empty string
2973  ********************************************************************/
2974
2975 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2976                                       int snum,
2977                                       struct spoolss_Notify *data,
2978                                       print_queue_struct *queue,
2979                                       struct spoolss_PrinterInfo2 *pinfo2,
2980                                       TALLOC_CTX *mem_ctx)
2981 {
2982         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2983 }
2984
2985 /*******************************************************************
2986  * fill a notify_info_data with the data type
2987  * jfm:xxxx always send RAW as data type
2988  ********************************************************************/
2989
2990 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2991                                     int snum,
2992                                     struct spoolss_Notify *data,
2993                                     print_queue_struct *queue,
2994                                     struct spoolss_PrinterInfo2 *pinfo2,
2995                                     TALLOC_CTX *mem_ctx)
2996 {
2997         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2998 }
2999
3000 /*******************************************************************
3001  * fill a notify_info_data with the security descriptor
3002  * jfm:xxxx send an null pointer to say no security desc
3003  * have to implement security before !
3004  ********************************************************************/
3005
3006 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
3007                                          int snum,
3008                                          struct spoolss_Notify *data,
3009                                          print_queue_struct *queue,
3010                                          struct spoolss_PrinterInfo2 *pinfo2,
3011                                          TALLOC_CTX *mem_ctx)
3012 {
3013         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
3014 }
3015
3016 /*******************************************************************
3017  * fill a notify_info_data with the attributes
3018  * jfm:xxxx a samba printer is always shared
3019  ********************************************************************/
3020
3021 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
3022                                       int snum,
3023                                       struct spoolss_Notify *data,
3024                                       print_queue_struct *queue,
3025                                       struct spoolss_PrinterInfo2 *pinfo2,
3026                                       TALLOC_CTX *mem_ctx)
3027 {
3028         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
3029 }
3030
3031 /*******************************************************************
3032  * fill a notify_info_data with the priority
3033  ********************************************************************/
3034
3035 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3036                                     int snum,
3037                                     struct spoolss_Notify *data,
3038                                     print_queue_struct *queue,
3039                                     struct spoolss_PrinterInfo2 *pinfo2,
3040                                     TALLOC_CTX *mem_ctx)
3041 {
3042         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3043 }
3044
3045 /*******************************************************************
3046  * fill a notify_info_data with the default priority
3047  ********************************************************************/
3048
3049 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3050                                             int snum,
3051                                             struct spoolss_Notify *data,
3052                                             print_queue_struct *queue,
3053                                             struct spoolss_PrinterInfo2 *pinfo2,
3054                                             TALLOC_CTX *mem_ctx)
3055 {
3056         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3057 }
3058
3059 /*******************************************************************
3060  * fill a notify_info_data with the start time
3061  ********************************************************************/
3062
3063 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3064                                       int snum,
3065                                       struct spoolss_Notify *data,
3066                                       print_queue_struct *queue,
3067                                       struct spoolss_PrinterInfo2 *pinfo2,
3068                                       TALLOC_CTX *mem_ctx)
3069 {
3070         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3071 }
3072
3073 /*******************************************************************
3074  * fill a notify_info_data with the until time
3075  ********************************************************************/
3076
3077 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3078                                       int snum,
3079                                       struct spoolss_Notify *data,
3080                                       print_queue_struct *queue,
3081                                       struct spoolss_PrinterInfo2 *pinfo2,
3082                                       TALLOC_CTX *mem_ctx)
3083 {
3084         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3085 }
3086
3087 /*******************************************************************
3088  * fill a notify_info_data with the status
3089  ********************************************************************/
3090
3091 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3092                                   int snum,
3093                                   struct spoolss_Notify *data,
3094                                   print_queue_struct *queue,
3095                                   struct spoolss_PrinterInfo2 *pinfo2,
3096                                   TALLOC_CTX *mem_ctx)
3097 {
3098         print_status_struct status;
3099
3100         print_queue_length(msg_ctx, snum, &status);
3101         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3102 }
3103
3104 /*******************************************************************
3105  * fill a notify_info_data with the number of jobs queued
3106  ********************************************************************/
3107
3108 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3109                                  int snum,
3110                                  struct spoolss_Notify *data,
3111                                  print_queue_struct *queue,
3112                                  struct spoolss_PrinterInfo2 *pinfo2,
3113                                  TALLOC_CTX *mem_ctx)
3114 {
3115         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3116                 data, print_queue_length(msg_ctx, snum, NULL));
3117 }
3118
3119 /*******************************************************************
3120  * fill a notify_info_data with the average ppm
3121  ********************************************************************/
3122
3123 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3124                                        int snum,
3125                                        struct spoolss_Notify *data,
3126                                        print_queue_struct *queue,
3127                                        struct spoolss_PrinterInfo2 *pinfo2,
3128                                        TALLOC_CTX *mem_ctx)
3129 {
3130         /* always respond 8 pages per minutes */
3131         /* a little hard ! */
3132         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3133 }
3134
3135 /*******************************************************************
3136  * fill a notify_info_data with username
3137  ********************************************************************/
3138
3139 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3140                                     int snum,
3141                                     struct spoolss_Notify *data,
3142                                     print_queue_struct *queue,
3143                                     struct spoolss_PrinterInfo2 *pinfo2,
3144                                     TALLOC_CTX *mem_ctx)
3145 {
3146         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3147 }
3148
3149 /*******************************************************************
3150  * fill a notify_info_data with job status
3151  ********************************************************************/
3152
3153 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3154                                       int snum,
3155                                       struct spoolss_Notify *data,
3156                                       print_queue_struct *queue,
3157                                       struct spoolss_PrinterInfo2 *pinfo2,
3158                                       TALLOC_CTX *mem_ctx)
3159 {
3160         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3161 }
3162
3163 /*******************************************************************
3164  * fill a notify_info_data with job name
3165  ********************************************************************/
3166
3167 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3168                                     int snum,
3169                                     struct spoolss_Notify *data,
3170                                     print_queue_struct *queue,
3171                                     struct spoolss_PrinterInfo2 *pinfo2,
3172                                     TALLOC_CTX *mem_ctx)
3173 {
3174         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3175 }
3176
3177 /*******************************************************************
3178  * fill a notify_info_data with job status
3179  ********************************************************************/
3180
3181 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3182                                              int snum,
3183                                              struct spoolss_Notify *data,
3184                                              print_queue_struct *queue,
3185                                              struct spoolss_PrinterInfo2 *pinfo2,
3186                                              TALLOC_CTX *mem_ctx)
3187 {
3188         /*
3189          * Now we're returning job status codes we just return a "" here. JRA.
3190          */
3191
3192         const char *p = "";
3193
3194 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3195         p = "unknown";
3196
3197         switch (queue->status) {
3198         case LPQ_QUEUED:
3199                 p = "Queued";
3200                 break;
3201         case LPQ_PAUSED:
3202                 p = "";    /* NT provides the paused string */
3203                 break;
3204         case LPQ_SPOOLING:
3205                 p = "Spooling";
3206                 break;
3207         case LPQ_PRINTING:
3208                 p = "Printing";
3209                 break;
3210         }
3211 #endif /* NO LONGER NEEDED. */
3212
3213         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3214 }
3215
3216 /*******************************************************************
3217  * fill a notify_info_data with job time
3218  ********************************************************************/
3219
3220 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3221                                     int snum,
3222                                     struct spoolss_Notify *data,
3223                                     print_queue_struct *queue,
3224                                     struct spoolss_PrinterInfo2 *pinfo2,
3225                                     TALLOC_CTX *mem_ctx)
3226 {
3227         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3228 }
3229
3230 /*******************************************************************
3231  * fill a notify_info_data with job size
3232  ********************************************************************/
3233
3234 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3235                                     int snum,
3236                                     struct spoolss_Notify *data,
3237                                     print_queue_struct *queue,
3238                                     struct spoolss_PrinterInfo2 *pinfo2,
3239                                     TALLOC_CTX *mem_ctx)
3240 {
3241         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3242 }
3243
3244 /*******************************************************************
3245  * fill a notify_info_data with page info
3246  ********************************************************************/
3247 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3248                                        int snum,
3249                                 struct spoolss_Notify *data,
3250                                 print_queue_struct *queue,
3251                                 struct spoolss_PrinterInfo2 *pinfo2,
3252                                 TALLOC_CTX *mem_ctx)
3253 {
3254         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3255 }
3256
3257 /*******************************************************************
3258  * fill a notify_info_data with pages printed info.
3259  ********************************************************************/
3260 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3261                                          int snum,
3262                                 struct spoolss_Notify *data,
3263                                 print_queue_struct *queue,
3264                                 struct spoolss_PrinterInfo2 *pinfo2,
3265                                 TALLOC_CTX *mem_ctx)
3266 {
3267         /* Add code when back-end tracks this */
3268         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3269 }
3270
3271 /*******************************************************************
3272  Fill a notify_info_data with job position.
3273  ********************************************************************/
3274
3275 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3276                                         int snum,
3277                                         struct spoolss_Notify *data,
3278                                         print_queue_struct *queue,
3279                                         struct spoolss_PrinterInfo2 *pinfo2,
3280                                         TALLOC_CTX *mem_ctx)
3281 {
3282         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3283 }
3284
3285 /*******************************************************************
3286  Fill a notify_info_data with submitted time.
3287  ********************************************************************/
3288
3289 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3290                                           int snum,
3291                                           struct spoolss_Notify *data,
3292                                           print_queue_struct *queue,
3293                                           struct spoolss_PrinterInfo2 *pinfo2,
3294                                           TALLOC_CTX *mem_ctx)
3295 {
3296         data->data.string.string = NULL;
3297         data->data.string.size = 0;
3298
3299         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3300                                &data->data.string.string,
3301                                &data->data.string.size);
3302
3303 }
3304
3305 struct s_notify_info_data_table
3306 {
3307         enum spoolss_NotifyType type;
3308         uint16_t field;
3309         const char *name;
3310         enum spoolss_NotifyTable variable_type;
3311         void (*fn) (struct messaging_context *msg_ctx,
3312                     int snum, struct spoolss_Notify *data,
3313                     print_queue_struct *queue,
3314                     struct spoolss_PrinterInfo2 *pinfo2,
3315                     TALLOC_CTX *mem_ctx);
3316 };
3317
3318 /* A table describing the various print notification constants and
3319    whether the notification data is a pointer to a variable sized
3320    buffer, a one value uint32_t or a two value uint32_t. */
3321
3322 static const struct s_notify_info_data_table notify_info_data_table[] =
3323 {
3324 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3325 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3326 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3327 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3328 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3329 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3330 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3331 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3332 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3333 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3334 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3335 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3336 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3337 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3338 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3339 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3340 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3341 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3342 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3343 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3344 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3345 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3346 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3347 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3348 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3349 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3350 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3351 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3352 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3353 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3354 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3355 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3356 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3357 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3358 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3359 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3360 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3361 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3362 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3363 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3364 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3365 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3366 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3367 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3368 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3369 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3370 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3371 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3372 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3373 };
3374
3375 /*******************************************************************
3376  Return the variable_type of info_data structure.
3377 ********************************************************************/
3378
3379 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3380                                                                   uint16_t field)
3381 {
3382         int i=0;
3383
3384         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3385                 if ( (notify_info_data_table[i].type == type) &&
3386                      (notify_info_data_table[i].field == field) ) {
3387                         return notify_info_data_table[i].variable_type;
3388                 }
3389         }
3390
3391         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3392
3393         return (enum spoolss_NotifyTable) 0;
3394 }
3395
3396 /****************************************************************************
3397 ****************************************************************************/
3398
3399 static bool search_notify(enum spoolss_NotifyType type,
3400                           uint16_t field,
3401                           int *value)
3402 {
3403         int i;
3404
3405         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3406                 if (notify_info_data_table[i].type == type &&
3407                     notify_info_data_table[i].field == field &&
3408                     notify_info_data_table[i].fn != NULL) {
3409                         *value = i;
3410                         return true;
3411                 }
3412         }
3413
3414         return false;
3415 }
3416
3417 /****************************************************************************
3418 ****************************************************************************/
3419
3420 static void construct_info_data(struct spoolss_Notify *info_data,
3421                                 enum spoolss_NotifyType type,
3422                                 uint16_t field, int id)
3423 {
3424         info_data->type                 = type;
3425         info_data->field.field          = field;
3426         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3427         info_data->job_id               = id;
3428 }
3429
3430 /*******************************************************************
3431  *
3432  * fill a notify_info struct with info asked
3433  *
3434  ********************************************************************/
3435
3436 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3437                                           struct printer_handle *print_hnd,
3438                                           struct spoolss_NotifyInfo *info,
3439                                           struct spoolss_PrinterInfo2 *pinfo2,
3440                                           int snum,
3441                                           const struct spoolss_NotifyOptionType *option_type,
3442                                           uint32_t id,
3443                                           TALLOC_CTX *mem_ctx)
3444 {
3445         int field_num,j;
3446         enum spoolss_NotifyType type;
3447         uint16_t field;
3448
3449         struct spoolss_Notify *current_data;
3450
3451         type = option_type->type;
3452
3453         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3454                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3455                 option_type->count, lp_servicename(snum)));
3456
3457         for(field_num=0; field_num < option_type->count; field_num++) {
3458                 field = option_type->fields[field_num].field;
3459
3460                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3461
3462                 if (!search_notify(type, field, &j) )
3463                         continue;
3464
3465                 info->notifies = talloc_realloc(info, info->notifies,
3466                                                       struct spoolss_Notify,
3467                                                       info->count + 1);
3468                 if (info->notifies == NULL) {
3469                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3470                         return false;
3471                 }
3472
3473                 current_data = &info->notifies[info->count];
3474
3475                 construct_info_data(current_data, type, field, id);
3476
3477                 DEBUG(10, ("construct_notify_printer_info: "
3478                            "calling [%s]  snum=%d  printername=[%s])\n",
3479                            notify_info_data_table[j].name, snum,
3480                            pinfo2->printername));
3481
3482                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3483                                              NULL, pinfo2, mem_ctx);
3484
3485                 info->count++;
3486         }
3487
3488         return true;
3489 }
3490
3491 /*******************************************************************
3492  *
3493  * fill a notify_info struct with info asked
3494  *
3495  ********************************************************************/
3496
3497 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3498                                        print_queue_struct *queue,
3499                                        struct spoolss_NotifyInfo *info,
3500                                        struct spoolss_PrinterInfo2 *pinfo2,
3501                                        int snum,
3502                                        const struct spoolss_NotifyOptionType *option_type,
3503                                        uint32_t id,
3504                                        TALLOC_CTX *mem_ctx)
3505 {
3506         int field_num,j;
3507         enum spoolss_NotifyType type;
3508         uint16_t field;
3509         struct spoolss_Notify *current_data;
3510
3511         DEBUG(4,("construct_notify_jobs_info\n"));
3512
3513         type = option_type->type;
3514
3515         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3516                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3517                 option_type->count));
3518
3519         for(field_num=0; field_num<option_type->count; field_num++) {
3520                 field = option_type->fields[field_num].field;
3521
3522                 if (!search_notify(type, field, &j) )
3523                         continue;
3524
3525                 info->notifies = talloc_realloc(info, info->notifies,
3526                                                       struct spoolss_Notify,
3527                                                       info->count + 1);
3528                 if (info->notifies == NULL) {
3529                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3530                         return false;
3531                 }
3532
3533                 current_data=&(info->notifies[info->count]);
3534
3535                 construct_info_data(current_data, type, field, id);
3536                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3537                                              queue, pinfo2, mem_ctx);
3538                 info->count++;
3539         }
3540
3541         return true;
3542 }
3543
3544 /*
3545  * JFM: The enumeration is not that simple, it's even non obvious.
3546  *
3547  * let's take an example: I want to monitor the PRINTER SERVER for
3548  * the printer's name and the number of jobs currently queued.
3549  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3550  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3551  *
3552  * I have 3 printers on the back of my server.
3553  *
3554  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3555  * structures.
3556  *   Number     Data                    Id
3557  *      1       printer 1 name          1
3558  *      2       printer 1 cjob          1
3559  *      3       printer 2 name          2
3560  *      4       printer 2 cjob          2
3561  *      5       printer 3 name          3
3562  *      6       printer 3 name          3
3563  *
3564  * that's the print server case, the printer case is even worse.
3565  */
3566
3567 /*******************************************************************
3568  *
3569  * enumerate all printers on the printserver
3570  * fill a notify_info struct with info asked
3571  *
3572  ********************************************************************/
3573
3574 static WERROR printserver_notify_info(struct pipes_struct *p,
3575                                       struct policy_handle *hnd,
3576                                       struct spoolss_NotifyInfo *info,
3577                                       TALLOC_CTX *mem_ctx)
3578 {
3579         int snum;
3580         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3581         int n_services=lp_numservices();
3582         int i;
3583         struct spoolss_NotifyOption *option;
3584         struct spoolss_NotifyOptionType option_type;
3585         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3586         WERROR result;
3587
3588         DEBUG(4,("printserver_notify_info\n"));
3589
3590         if (!Printer)
3591                 return WERR_BADFID;
3592
3593         option = Printer->notify.option;
3594
3595         info->version   = 2;
3596         info->notifies  = NULL;
3597         info->count     = 0;
3598
3599         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3600            sending a ffpcn() request first */
3601
3602         if ( !option )
3603                 return WERR_BADFID;
3604
3605         for (i=0; i<option->count; i++) {
3606                 option_type = option->types[i];
3607
3608                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3609                         continue;
3610
3611                 for (snum = 0; snum < n_services; snum++) {
3612                         if (!lp_browseable(snum) ||
3613                             !lp_snum_ok(snum) ||
3614                             !lp_print_ok(snum)) {
3615                                 continue; /* skip */
3616                         }
3617
3618                         /* Maybe we should use the SYSTEM session_info here... */
3619                         result = winreg_get_printer_internal(mem_ctx,
3620                                                     get_session_info_system(),
3621                                                     p->msg_ctx,
3622                                                     lp_servicename(snum),
3623                                                     &pinfo2);
3624                         if (!W_ERROR_IS_OK(result)) {
3625                                 DEBUG(4, ("printserver_notify_info: "
3626                                           "Failed to get printer [%s]\n",
3627                                           lp_servicename(snum)));
3628                                 continue;
3629                         }
3630
3631
3632                         construct_notify_printer_info(p->msg_ctx,
3633                                                       Printer, info,
3634                                                       pinfo2, snum,
3635                                                       &option_type, snum,
3636                                                       mem_ctx);
3637
3638                         TALLOC_FREE(pinfo2);
3639                 }
3640         }
3641
3642 #if 0
3643         /*
3644          * Debugging information, don't delete.
3645          */
3646
3647         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3648         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3649         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3650
3651         for (i=0; i<info->count; i++) {
3652                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3653                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3654                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3655         }
3656 #endif
3657
3658         return WERR_OK;
3659 }
3660
3661 /*******************************************************************
3662  *
3663  * fill a notify_info struct with info asked
3664  *
3665  ********************************************************************/
3666
3667 static WERROR printer_notify_info(struct pipes_struct *p,
3668                                   struct policy_handle *hnd,
3669                                   struct spoolss_NotifyInfo *info,
3670                                   TALLOC_CTX *mem_ctx)
3671 {
3672         int snum;
3673         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3674         int i;
3675         uint32_t id;
3676         struct spoolss_NotifyOption *option;
3677         struct spoolss_NotifyOptionType option_type;
3678         int count,j;
3679         print_queue_struct *queue=NULL;
3680         print_status_struct status;
3681         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3682         WERROR result;
3683
3684         DEBUG(4,("printer_notify_info\n"));
3685
3686         if (!Printer)
3687                 return WERR_BADFID;
3688
3689         option = Printer->notify.option;
3690         id = 0x0;
3691
3692         info->version   = 2;
3693         info->notifies  = NULL;
3694         info->count     = 0;
3695
3696         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3697            sending a ffpcn() request first */
3698
3699         if ( !option )
3700                 return WERR_BADFID;
3701
3702         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3703                 return WERR_BADFID;
3704         }
3705
3706         /* Maybe we should use the SYSTEM session_info here... */
3707         result = winreg_get_printer_internal(mem_ctx,
3708                                     get_session_info_system(),
3709                                     p->msg_ctx,
3710                                     lp_servicename(snum), &pinfo2);
3711         if (!W_ERROR_IS_OK(result)) {
3712                 return WERR_BADFID;
3713         }
3714
3715         /*
3716          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3717          * correct servername.
3718          */
3719         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3720         if (pinfo2->servername == NULL) {
3721                 return WERR_NOMEM;
3722         }
3723
3724         for (i=0; i<option->count; i++) {
3725                 option_type = option->types[i];
3726
3727                 switch (option_type.type) {
3728                 case PRINTER_NOTIFY_TYPE:
3729                         if (construct_notify_printer_info(p->msg_ctx,
3730                                                           Printer, info,
3731                                                           pinfo2, snum,
3732                                                           &option_type, id,
3733                                                           mem_ctx)) {
3734                                 id--;
3735                         }
3736                         break;
3737
3738                 case JOB_NOTIFY_TYPE:
3739
3740                         count = print_queue_status(p->msg_ctx, snum, &queue,
3741                                                    &status);
3742
3743                         for (j=0; j<count; j++) {
3744                                 construct_notify_jobs_info(p->msg_ctx,
3745                                                            &queue[j], info,
3746                                                            pinfo2, snum,
3747                                                            &option_type,
3748                                                            queue[j].job,
3749                                                            mem_ctx);
3750                         }
3751
3752                         SAFE_FREE(queue);
3753                         break;
3754                 }
3755         }
3756
3757         /*
3758          * Debugging information, don't delete.
3759          */
3760         /*
3761         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3762         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3763         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3764
3765         for (i=0; i<info->count; i++) {
3766                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3767                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3768                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3769         }
3770         */
3771
3772         talloc_free(pinfo2);
3773         return WERR_OK;
3774 }
3775
3776 /****************************************************************
3777  _spoolss_RouterRefreshPrinterChangeNotify
3778 ****************************************************************/
3779
3780 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3781                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3782 {
3783         struct spoolss_NotifyInfo *info;
3784
3785         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3786         WERROR result = WERR_BADFID;
3787
3788         /* we always have a spoolss_NotifyInfo struct */
3789         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3790         if (!info) {
3791                 result = WERR_NOMEM;
3792                 goto done;
3793         }
3794
3795         *r->out.info = info;
3796
3797         if (!Printer) {
3798                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3799                         "Invalid handle (%s:%u:%u).\n",
3800                         OUR_HANDLE(r->in.handle)));
3801                 goto done;
3802         }
3803
3804         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3805
3806         /*
3807          *      We are now using the change value, and
3808          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3809          *      I don't have a global notification system, I'm sending back all the
3810          *      information even when _NOTHING_ has changed.
3811          */
3812
3813         /* We need to keep track of the change value to send back in
3814            RRPCN replies otherwise our updates are ignored. */
3815
3816         Printer->notify.fnpcn = true;
3817
3818         if (Printer->notify.cli_chan != NULL &&
3819             Printer->notify.cli_chan->active_connections > 0) {
3820                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3821                         "Saving change value in request [%x]\n",
3822                         r->in.change_low));
3823                 Printer->notify.change = r->in.change_low;
3824         }
3825
3826         /* just ignore the spoolss_NotifyOption */
3827
3828         switch (Printer->printer_type) {
3829                 case SPLHND_SERVER:
3830                         result = printserver_notify_info(p, r->in.handle,
3831                                                          info, p->mem_ctx);
3832                         break;
3833
3834                 case SPLHND_PRINTER:
3835                         result = printer_notify_info(p, r->in.handle,
3836                                                      info, p->mem_ctx);
3837                         break;
3838         }
3839
3840         Printer->notify.fnpcn = false;
3841
3842 done:
3843         return result;
3844 }
3845
3846 /********************************************************************
3847  ********************************************************************/
3848
3849 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3850                                  const char *servername,
3851                                  const char *printername,
3852                                  const char **printername_p)
3853 {
3854         /* FIXME: add lp_force_printername() */
3855
3856         if (servername == NULL) {
3857                 *printername_p = talloc_strdup(mem_ctx, printername);
3858                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3859                 return WERR_OK;
3860         }
3861
3862         if (servername[0] == '\\' && servername[1] == '\\') {
3863                 servername += 2;
3864         }
3865
3866         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3867         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3868
3869         return WERR_OK;
3870 }
3871
3872 /********************************************************************
3873  ********************************************************************/
3874
3875 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3876                                           const char *printername)
3877 {
3878         if (dm == NULL) {
3879                 return;
3880         }
3881
3882         dm->devicename = talloc_strndup(dm, printername,
3883                                         MIN(strlen(printername), 31));
3884 }
3885
3886 /********************************************************************
3887  * construct_printer_info_0
3888  * fill a printer_info_0 struct
3889  ********************************************************************/
3890
3891 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3892                                       const struct auth_session_info *session_info,
3893                                       struct messaging_context *msg_ctx,
3894                                       struct spoolss_PrinterInfo2 *info2,
3895                                       const char *servername,
3896                                       struct spoolss_PrinterInfo0 *r,
3897                                       int snum)
3898 {
3899         int count;
3900         struct printer_session_counter *session_counter;
3901         struct timeval setuptime;
3902         print_status_struct status;
3903         WERROR result;
3904
3905         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3906         if (!W_ERROR_IS_OK(result)) {
3907                 return result;
3908         }
3909
3910         if (servername) {
3911                 r->servername = talloc_strdup(mem_ctx, servername);
3912                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3913         } else {
3914                 r->servername = NULL;
3915         }
3916
3917         count = print_queue_length(msg_ctx, snum, &status);
3918
3919         /* check if we already have a counter for this printer */
3920         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3921                 if (session_counter->snum == snum)
3922                         break;
3923         }
3924
3925         /* it's the first time, add it to the list */
3926         if (session_counter == NULL) {
3927                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3928                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3929                 session_counter->snum           = snum;
3930                 session_counter->counter        = 0;
3931                 DLIST_ADD(counter_list, session_counter);
3932         }
3933
3934         /* increment it */
3935         session_counter->counter++;
3936
3937         r->cjobs                        = count;
3938         r->total_jobs                   = 0;
3939         r->total_bytes                  = 0;
3940
3941         get_startup_time(&setuptime);
3942         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3943
3944         /* JFM:
3945          * the global_counter should be stored in a TDB as it's common to all the clients
3946          * and should be zeroed on samba startup
3947          */
3948         r->global_counter               = session_counter->counter;
3949         r->total_pages                  = 0;
3950         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3951         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3952         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3953         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3954         r->spooling                     = 0;
3955         r->max_spooling                 = 0;
3956         r->session_counter              = session_counter->counter;
3957         r->num_error_out_of_paper       = 0x0;
3958         r->num_error_not_ready          = 0x0;          /* number of print failure */
3959         r->job_error                    = 0x0;
3960         r->number_of_processors         = 0x1;
3961         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3962         r->high_part_total_bytes        = 0x0;
3963
3964         /* ChangeID in milliseconds*/
3965         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3966                                     info2->sharename, &r->change_id);
3967
3968         r->last_error                   = WERR_OK;
3969         r->status                       = nt_printq_status(status.status);
3970         r->enumerate_network_printers   = 0x0;
3971         r->c_setprinter                 = 0x0;
3972         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3973         r->processor_level              = 0x6;          /* 6  ???*/
3974         r->ref_ic                       = 0;
3975         r->reserved2                    = 0;
3976         r->reserved3                    = 0;
3977
3978         return WERR_OK;
3979 }
3980
3981
3982 /********************************************************************
3983  * construct_printer_info1
3984  * fill a spoolss_PrinterInfo1 struct
3985 ********************************************************************/
3986
3987 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3988                                       const struct spoolss_PrinterInfo2 *info2,
3989                                       uint32_t flags,
3990                                       const char *servername,
3991                                       struct spoolss_PrinterInfo1 *r,
3992                                       int snum)
3993 {
3994         WERROR result;
3995
3996         r->flags                = flags;
3997
3998         if (info2->comment == NULL || info2->comment[0] == '\0') {
3999                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4000         } else {
4001                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
4002         }
4003         W_ERROR_HAVE_NO_MEMORY(r->comment);
4004
4005         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
4006         if (!W_ERROR_IS_OK(result)) {
4007                 return result;
4008         }
4009
4010         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
4011                                                   r->name,
4012                                                   info2->drivername,
4013                                                   r->comment);
4014         W_ERROR_HAVE_NO_MEMORY(r->description);
4015
4016         return WERR_OK;
4017 }
4018
4019 /********************************************************************
4020  * construct_printer_info2
4021  * fill a spoolss_PrinterInfo2 struct
4022 ********************************************************************/
4023
4024 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4025                                       struct messaging_context *msg_ctx,
4026                                       const struct spoolss_PrinterInfo2 *info2,
4027                                       const char *servername,
4028                                       struct spoolss_PrinterInfo2 *r,
4029                                       int snum)
4030 {
4031         int count;
4032         print_status_struct status;
4033         WERROR result;
4034
4035         count = print_queue_length(msg_ctx, snum, &status);
4036
4037         if (servername) {
4038                 r->servername           = talloc_strdup(mem_ctx, servername);
4039                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4040         } else {
4041                 r->servername           = NULL;
4042         }
4043
4044         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4045         if (!W_ERROR_IS_OK(result)) {
4046                 return result;
4047         }
4048
4049         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
4050         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4051         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4052         W_ERROR_HAVE_NO_MEMORY(r->portname);
4053         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4054         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4055
4056         if (info2->comment[0] == '\0') {
4057                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4058         } else {
4059                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4060         }
4061         W_ERROR_HAVE_NO_MEMORY(r->comment);
4062
4063         r->location     = talloc_strdup(mem_ctx, info2->location);
4064         if (info2->location[0] == '\0') {
4065                 const char *loc = NULL;
4066                 NTSTATUS nt_status;
4067
4068                 nt_status = printer_list_get_printer(mem_ctx,
4069                                                      info2->sharename,
4070                                                      NULL,
4071                                                      &loc,
4072                                                      NULL);
4073                 if (NT_STATUS_IS_OK(nt_status)) {
4074                         if (loc != NULL) {
4075                                 r->location = talloc_strdup(mem_ctx, loc);
4076                         }
4077                 }
4078         }
4079         W_ERROR_HAVE_NO_MEMORY(r->location);
4080
4081         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4082         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4083         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4084         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4085         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4086         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4087         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4088         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4089
4090         r->attributes           = info2->attributes;
4091
4092         r->priority             = info2->priority;
4093         r->defaultpriority      = info2->defaultpriority;
4094         r->starttime            = info2->starttime;
4095         r->untiltime            = info2->untiltime;
4096         r->status               = nt_printq_status(status.status);
4097         r->cjobs                = count;
4098         r->averageppm           = info2->averageppm;
4099
4100         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4101         if (!r->devmode) {
4102                 DEBUG(8,("Returning NULL Devicemode!\n"));
4103         }
4104
4105         compose_devicemode_devicename(r->devmode, r->printername);
4106
4107         r->secdesc = NULL;
4108
4109         if (info2->secdesc != NULL) {
4110                 /* don't use talloc_steal() here unless you do a deep steal of all
4111                    the SEC_DESC members */
4112
4113                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4114         }
4115
4116         return WERR_OK;
4117 }
4118
4119 /********************************************************************
4120  * construct_printer_info3
4121  * fill a spoolss_PrinterInfo3 struct
4122  ********************************************************************/
4123
4124 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4125                                       const struct spoolss_PrinterInfo2 *info2,
4126                                       const char *servername,
4127                                       struct spoolss_PrinterInfo3 *r,
4128                                       int snum)
4129 {
4130         /* These are the components of the SD we are returning. */
4131
4132         if (info2->secdesc != NULL) {
4133                 /* don't use talloc_steal() here unless you do a deep steal of all
4134                    the SEC_DESC members */
4135
4136                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4137                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4138         }
4139
4140         return WERR_OK;
4141 }
4142
4143 /********************************************************************
4144  * construct_printer_info4
4145  * fill a spoolss_PrinterInfo4 struct
4146  ********************************************************************/
4147
4148 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4149                                       const struct spoolss_PrinterInfo2 *info2,
4150                                       const char *servername,
4151                                       struct spoolss_PrinterInfo4 *r,
4152                                       int snum)
4153 {
4154         WERROR result;
4155
4156         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4157         if (!W_ERROR_IS_OK(result)) {
4158                 return result;
4159         }
4160
4161         if (servername) {
4162                 r->servername   = talloc_strdup(mem_ctx, servername);
4163                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4164         } else {
4165                 r->servername = NULL;
4166         }
4167
4168         r->attributes   = info2->attributes;
4169
4170         return WERR_OK;
4171 }
4172
4173 /********************************************************************
4174  * construct_printer_info5
4175  * fill a spoolss_PrinterInfo5 struct
4176  ********************************************************************/
4177
4178 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4179                                       const struct spoolss_PrinterInfo2 *info2,
4180                                       const char *servername,
4181                                       struct spoolss_PrinterInfo5 *r,
4182                                       int snum)
4183 {
4184         WERROR result;
4185
4186         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4187         if (!W_ERROR_IS_OK(result)) {
4188                 return result;
4189         }
4190
4191         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4192         W_ERROR_HAVE_NO_MEMORY(r->portname);
4193
4194         r->attributes   = info2->attributes;
4195
4196         /* these two are not used by NT+ according to MSDN */
4197         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4198         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4199
4200         return WERR_OK;
4201 }
4202
4203 /********************************************************************
4204  * construct_printer_info_6
4205  * fill a spoolss_PrinterInfo6 struct
4206  ********************************************************************/
4207
4208 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4209                                       struct messaging_context *msg_ctx,
4210                                       const struct spoolss_PrinterInfo2 *info2,
4211                                       const char *servername,
4212                                       struct spoolss_PrinterInfo6 *r,
4213                                       int snum)
4214 {
4215         print_status_struct status;
4216
4217         print_queue_length(msg_ctx, snum, &status);
4218
4219         r->status = nt_printq_status(status.status);
4220
4221         return WERR_OK;
4222 }
4223
4224 /********************************************************************
4225  * construct_printer_info7
4226  * fill a spoolss_PrinterInfo7 struct
4227  ********************************************************************/
4228
4229 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4230                                       struct messaging_context *msg_ctx,
4231                                       const char *servername,
4232                                       struct spoolss_PrinterInfo7 *r,
4233                                       int snum)
4234 {
4235         const struct auth_session_info *session_info = get_session_info_system();
4236         struct GUID guid;
4237
4238         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4239                                  servername,
4240                                  lp_servicename(snum), &guid, NULL)) {
4241                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4242                 r->action = DSPRINT_PUBLISH;
4243         } else {
4244                 r->guid = talloc_strdup(mem_ctx, "");
4245                 r->action = DSPRINT_UNPUBLISH;
4246         }
4247         W_ERROR_HAVE_NO_MEMORY(r->guid);
4248
4249         return WERR_OK;
4250 }
4251
4252 /********************************************************************
4253  * construct_printer_info8
4254  * fill a spoolss_PrinterInfo8 struct
4255  ********************************************************************/
4256
4257 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4258                                       const struct spoolss_PrinterInfo2 *info2,
4259                                       const char *servername,
4260                                       struct spoolss_DeviceModeInfo *r,
4261                                       int snum)
4262 {
4263         WERROR result;
4264         const char *printername;
4265
4266         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4267         if (!W_ERROR_IS_OK(result)) {
4268                 return result;
4269         }
4270
4271         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4272         if (!r->devmode) {
4273                 DEBUG(8,("Returning NULL Devicemode!\n"));
4274         }
4275
4276         compose_devicemode_devicename(r->devmode, printername);
4277
4278         return WERR_OK;
4279 }
4280
4281
4282 /********************************************************************
4283 ********************************************************************/
4284
4285 static bool snum_is_shared_printer(int snum)
4286 {
4287         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4288 }
4289
4290 /********************************************************************
4291  Spoolss_enumprinters.
4292 ********************************************************************/
4293
4294 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4295                                            const struct auth_session_info *session_info,
4296                                            struct messaging_context *msg_ctx,
4297                                            const char *servername,
4298                                            uint32_t level,
4299                                            uint32_t flags,
4300                                            union spoolss_PrinterInfo **info_p,
4301                                            uint32_t *count_p)
4302 {
4303         int snum;
4304         int n_services = lp_numservices();
4305         union spoolss_PrinterInfo *info = NULL;
4306         uint32_t count = 0;
4307         WERROR result = WERR_OK;
4308         struct dcerpc_binding_handle *b = NULL;
4309         TALLOC_CTX *tmp_ctx = NULL;
4310
4311         tmp_ctx = talloc_new(mem_ctx);
4312         if (!tmp_ctx) {
4313                 return WERR_NOMEM;
4314         }
4315
4316         *count_p = 0;
4317         *info_p = NULL;
4318
4319         for (snum = 0; snum < n_services; snum++) {
4320
4321                 const char *printer;
4322                 struct spoolss_PrinterInfo2 *info2;
4323
4324                 if (!snum_is_shared_printer(snum)) {
4325                         continue;
4326                 }
4327
4328                 printer = lp_const_servicename(snum);
4329
4330                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4331                         printer, snum));
4332
4333                 if (b == NULL) {
4334                         result = winreg_printer_binding_handle(tmp_ctx,
4335                                                                session_info,
4336                                                                msg_ctx,
4337                                                                &b);
4338                         if (!W_ERROR_IS_OK(result)) {
4339                                 goto out;
4340                         }
4341                 }
4342
4343                 result = winreg_create_printer(tmp_ctx, b,
4344                                                printer);
4345                 if (!W_ERROR_IS_OK(result)) {
4346                         goto out;
4347                 }
4348
4349                 info = talloc_realloc(tmp_ctx, info,
4350                                             union spoolss_PrinterInfo,
4351                                             count + 1);
4352                 if (!info) {
4353                         result = WERR_NOMEM;
4354                         goto out;
4355                 }
4356
4357                 result = winreg_get_printer(tmp_ctx, b,
4358                                             printer, &info2);
4359                 if (!W_ERROR_IS_OK(result)) {
4360                         goto out;
4361                 }
4362
4363                 switch (level) {
4364                 case 0:
4365                         result = construct_printer_info0(info, session_info,
4366                                                          msg_ctx, info2,
4367                                                          servername,
4368                                                          &info[count].info0, snum);
4369                         break;
4370                 case 1:
4371                         result = construct_printer_info1(info, info2, flags,
4372                                                          servername,
4373                                                          &info[count].info1, snum);
4374                         break;
4375                 case 2:
4376                         result = construct_printer_info2(info, msg_ctx, info2,
4377                                                          servername,
4378                                                          &info[count].info2, snum);
4379                         break;
4380                 case 4:
4381                         result = construct_printer_info4(info, info2,
4382                                                          servername,
4383                                                          &info[count].info4, snum);
4384                         break;
4385                 case 5:
4386                         result = construct_printer_info5(info, info2,
4387                                                          servername,
4388                                                          &info[count].info5, snum);
4389                         break;
4390
4391                 default:
4392                         result = WERR_UNKNOWN_LEVEL;
4393                         goto out;
4394                 }
4395
4396                 if (!W_ERROR_IS_OK(result)) {
4397                         goto out;
4398                 }
4399
4400                 count++;
4401         }
4402
4403 out:
4404         if (W_ERROR_IS_OK(result)) {
4405                 *info_p = talloc_move(mem_ctx, &info);
4406                 *count_p = count;
4407         }
4408
4409         talloc_free(tmp_ctx);
4410
4411         return result;
4412 }
4413
4414 /********************************************************************
4415  * handle enumeration of printers at level 0
4416  ********************************************************************/
4417
4418 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4419                                   const struct auth_session_info *session_info,
4420                                   struct messaging_context *msg_ctx,
4421                                   uint32_t flags,
4422                                   const char *servername,
4423                                   union spoolss_PrinterInfo **info,
4424                                   uint32_t *count)
4425 {
4426         DEBUG(4,("enum_all_printers_info_0\n"));
4427
4428         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4429                                             servername, 0, flags, info, count);
4430 }
4431
4432
4433 /********************************************************************
4434 ********************************************************************/
4435
4436 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4437                                        const struct auth_session_info *session_info,
4438                                        struct messaging_context *msg_ctx,
4439                                        const char *servername,
4440                                        uint32_t flags,
4441                                        union spoolss_PrinterInfo **info,
4442                                        uint32_t *count)
4443 {
4444         DEBUG(4,("enum_all_printers_info_1\n"));
4445
4446         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4447                                             servername, 1, flags, info, count);
4448 }
4449
4450 /********************************************************************
4451  enum_all_printers_info_1_local.
4452 *********************************************************************/
4453
4454 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4455                                              const struct auth_session_info *session_info,
4456                                              struct messaging_context *msg_ctx,
4457                                              const char *servername,
4458                                              union spoolss_PrinterInfo **info,
4459                                              uint32_t *count)
4460 {
4461         DEBUG(4,("enum_all_printers_info_1_local\n"));
4462
4463         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4464                                         servername, PRINTER_ENUM_ICON8, info, count);
4465 }
4466
4467 /********************************************************************
4468  enum_all_printers_info_1_name.
4469 *********************************************************************/
4470
4471 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4472                                             const struct auth_session_info *session_info,
4473                                             struct messaging_context *msg_ctx,
4474                                             const char *servername,
4475                                             union spoolss_PrinterInfo **info,
4476                                             uint32_t *count)
4477 {
4478         const char *s = servername;
4479
4480         DEBUG(4,("enum_all_printers_info_1_name\n"));
4481
4482         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4483                 s = servername + 2;
4484         }
4485
4486         if (!is_myname_or_ipaddr(s)) {
4487                 return WERR_INVALID_NAME;
4488         }
4489
4490         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4491                                         servername, PRINTER_ENUM_ICON8, info, count);
4492 }
4493
4494 /********************************************************************
4495  enum_all_printers_info_1_network.
4496 *********************************************************************/
4497
4498 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4499                                                const struct auth_session_info *session_info,
4500                                                struct messaging_context *msg_ctx,
4501                                                const char *servername,
4502                                                union spoolss_PrinterInfo **info,
4503                                                uint32_t *count)
4504 {
4505         const char *s = servername;
4506
4507         DEBUG(4,("enum_all_printers_info_1_network\n"));
4508
4509         /* If we respond to a enum_printers level 1 on our name with flags
4510            set to PRINTER_ENUM_REMOTE with a list of printers then these
4511            printers incorrectly appear in the APW browse list.
4512            Specifically the printers for the server appear at the workgroup
4513            level where all the other servers in the domain are
4514            listed. Windows responds to this call with a
4515            WERR_CAN_NOT_COMPLETE so we should do the same. */
4516
4517         if (servername[0] == '\\' && servername[1] == '\\') {
4518                  s = servername + 2;
4519         }
4520
4521         if (is_myname_or_ipaddr(s)) {
4522                  return WERR_CAN_NOT_COMPLETE;
4523         }
4524
4525         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4526                                         servername, PRINTER_ENUM_NAME, info, count);
4527 }
4528
4529 /********************************************************************
4530  * api_spoolss_enumprinters
4531  *
4532  * called from api_spoolss_enumprinters (see this to understand)
4533  ********************************************************************/
4534
4535 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4536                                        const struct auth_session_info *session_info,
4537                                        struct messaging_context *msg_ctx,
4538                                        const char *servername,
4539                                        union spoolss_PrinterInfo **info,
4540                                        uint32_t *count)
4541 {
4542         DEBUG(4,("enum_all_printers_info_2\n"));
4543
4544         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4545                                             servername, 2, 0, info, count);
4546 }
4547
4548 /********************************************************************
4549  * handle enumeration of printers at level 1
4550  ********************************************************************/
4551
4552 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4553                                   const struct auth_session_info *session_info,
4554                                   struct messaging_context *msg_ctx,
4555                                   uint32_t flags,
4556                                   const char *servername,
4557                                   union spoolss_PrinterInfo **info,
4558                                   uint32_t *count)
4559 {
4560         /* Not all the flags are equals */
4561
4562         if (flags & PRINTER_ENUM_LOCAL) {
4563                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4564                                                       msg_ctx, servername, info, count);
4565         }
4566
4567         if (flags & PRINTER_ENUM_NAME) {
4568                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4569                                                      msg_ctx, servername, info,
4570                                                      count);
4571         }
4572
4573         if (flags & PRINTER_ENUM_NETWORK) {
4574                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4575                                                         msg_ctx, servername, info,
4576                                                         count);
4577         }
4578
4579         return WERR_OK; /* NT4sp5 does that */
4580 }
4581
4582 /********************************************************************
4583  * handle enumeration of printers at level 2
4584  ********************************************************************/
4585
4586 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4587                                   const struct auth_session_info *session_info,
4588                                   struct messaging_context *msg_ctx,
4589                                   uint32_t flags,
4590                                   const char *servername,
4591                                   union spoolss_PrinterInfo **info,
4592                                   uint32_t *count)
4593 {
4594         if (flags & PRINTER_ENUM_LOCAL) {
4595
4596                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4597                                                 servername,
4598                                                 info, count);
4599         }
4600
4601         if (flags & PRINTER_ENUM_NAME) {
4602                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4603                         return WERR_INVALID_NAME;
4604                 }
4605
4606                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4607                                                 servername,
4608                                                 info, count);
4609         }
4610
4611         if (flags & PRINTER_ENUM_REMOTE) {
4612                 return WERR_UNKNOWN_LEVEL;
4613         }
4614
4615         return WERR_OK;
4616 }
4617
4618 /********************************************************************
4619  * handle enumeration of printers at level 4
4620  ********************************************************************/
4621
4622 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4623                                   const struct auth_session_info *session_info,
4624                                   struct messaging_context *msg_ctx,
4625                                   uint32_t flags,
4626                                   const char *servername,
4627                                   union spoolss_PrinterInfo **info,
4628                                   uint32_t *count)
4629 {
4630         DEBUG(4,("enum_all_printers_info_4\n"));
4631
4632         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4633                                             servername, 4, flags, info, count);
4634 }
4635
4636
4637 /********************************************************************
4638  * handle enumeration of printers at level 5
4639  ********************************************************************/
4640
4641 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4642                                   const struct auth_session_info *session_info,
4643                                   struct messaging_context *msg_ctx,
4644                                   uint32_t flags,
4645                                   const char *servername,
4646                                   union spoolss_PrinterInfo **info,
4647                                   uint32_t *count)
4648 {
4649         DEBUG(4,("enum_all_printers_info_5\n"));
4650
4651         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4652                                             servername, 5, flags, info, count);
4653 }
4654
4655 /****************************************************************
4656  _spoolss_EnumPrinters
4657 ****************************************************************/
4658
4659 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4660                              struct spoolss_EnumPrinters *r)
4661 {
4662         const struct auth_session_info *session_info = get_session_info_system();
4663         WERROR result;
4664
4665         /* that's an [in out] buffer */
4666
4667         if (!r->in.buffer && (r->in.offered != 0)) {
4668                 return WERR_INVALID_PARAM;
4669         }
4670
4671         DEBUG(4,("_spoolss_EnumPrinters\n"));
4672
4673         *r->out.needed = 0;
4674         *r->out.count = 0;
4675         *r->out.info = NULL;
4676
4677         /*
4678          * Level 1:
4679          *          flags==PRINTER_ENUM_NAME
4680          *           if name=="" then enumerates all printers
4681          *           if name!="" then enumerate the printer
4682          *          flags==PRINTER_ENUM_REMOTE
4683          *          name is NULL, enumerate printers
4684          * Level 2: name!="" enumerates printers, name can't be NULL
4685          * Level 3: doesn't exist
4686          * Level 4: does a local registry lookup
4687          * Level 5: same as Level 2
4688          */
4689
4690         if (r->in.server && r->in.server[0] == '\0') {
4691                 r->in.server = NULL;
4692         }
4693
4694         switch (r->in.level) {
4695         case 0:
4696                 result = enumprinters_level0(p->mem_ctx, session_info,
4697                                              p->msg_ctx, r->in.flags,
4698                                              r->in.server,
4699                                              r->out.info, r->out.count);
4700                 break;
4701         case 1:
4702                 result = enumprinters_level1(p->mem_ctx, session_info,
4703                                              p->msg_ctx, r->in.flags,
4704                                              r->in.server,
4705                                              r->out.info, r->out.count);
4706                 break;
4707         case 2:
4708                 result = enumprinters_level2(p->mem_ctx, session_info,
4709                                              p->msg_ctx, r->in.flags,
4710                                              r->in.server,
4711                                              r->out.info, r->out.count);
4712                 break;
4713         case 4:
4714                 result = enumprinters_level4(p->mem_ctx, session_info,
4715                                              p->msg_ctx, r->in.flags,
4716                                              r->in.server,
4717                                              r->out.info, r->out.count);
4718                 break;
4719         case 5:
4720                 result = enumprinters_level5(p->mem_ctx, session_info,
4721                                              p->msg_ctx, r->in.flags,
4722                                              r->in.server,
4723                                              r->out.info, r->out.count);
4724                 break;
4725         default:
4726                 return WERR_UNKNOWN_LEVEL;
4727         }
4728
4729         if (!W_ERROR_IS_OK(result)) {
4730                 return result;
4731         }
4732
4733         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4734                                                      spoolss_EnumPrinters,
4735                                                      *r->out.info, r->in.level,
4736                                                      *r->out.count);
4737         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4738         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4739
4740         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4741 }
4742
4743 /****************************************************************
4744  _spoolss_GetPrinter
4745 ****************************************************************/
4746
4747 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4748                            struct spoolss_GetPrinter *r)
4749 {
4750         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4751         struct spoolss_PrinterInfo2 *info2 = NULL;
4752         WERROR result = WERR_OK;
4753         int snum;
4754
4755         /* that's an [in out] buffer */
4756
4757         if (!r->in.buffer && (r->in.offered != 0)) {
4758                 return WERR_INVALID_PARAM;
4759         }
4760
4761         *r->out.needed = 0;
4762
4763         if (Printer == NULL) {
4764                 return WERR_BADFID;
4765         }
4766
4767         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4768                 return WERR_BADFID;
4769         }
4770
4771         result = winreg_get_printer_internal(p->mem_ctx,
4772                                     get_session_info_system(),
4773                                     p->msg_ctx,
4774                                     lp_const_servicename(snum),
4775                                     &info2);
4776         if (!W_ERROR_IS_OK(result)) {
4777                 goto out;
4778         }
4779
4780         switch (r->in.level) {
4781         case 0:
4782                 result = construct_printer_info0(p->mem_ctx,
4783                                                  get_session_info_system(),
4784                                                  p->msg_ctx,
4785                                                  info2,
4786                                                  Printer->servername,
4787                                                  &r->out.info->info0,
4788                                                  snum);
4789                 break;
4790         case 1:
4791                 result = construct_printer_info1(p->mem_ctx, info2,
4792                                                  PRINTER_ENUM_ICON8,
4793                                                  Printer->servername,
4794                                                  &r->out.info->info1, snum);
4795                 break;
4796         case 2:
4797                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4798                                                  Printer->servername,
4799                                                  &r->out.info->info2, snum);
4800                 break;
4801         case 3:
4802                 result = construct_printer_info3(p->mem_ctx, info2,
4803                                                  Printer->servername,
4804                                                  &r->out.info->info3, snum);
4805                 break;
4806         case 4:
4807                 result = construct_printer_info4(p->mem_ctx, info2,
4808                                                  Printer->servername,
4809                                                  &r->out.info->info4, snum);
4810                 break;
4811         case 5:
4812                 result = construct_printer_info5(p->mem_ctx, info2,
4813                                                  Printer->servername,
4814                                                  &r->out.info->info5, snum);
4815                 break;
4816         case 6:
4817                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4818                                                  Printer->servername,
4819                                                  &r->out.info->info6, snum);
4820                 break;
4821         case 7:
4822                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4823                                                  Printer->servername,
4824                                                  &r->out.info->info7, snum);
4825                 break;
4826         case 8:
4827                 result = construct_printer_info8(p->mem_ctx, info2,
4828                                                  Printer->servername,
4829                                                  &r->out.info->info8, snum);
4830                 break;
4831         default:
4832                 result = WERR_UNKNOWN_LEVEL;
4833                 break;
4834         }
4835         TALLOC_FREE(info2);
4836
4837  out:
4838         if (!W_ERROR_IS_OK(result)) {
4839                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4840                           r->in.level, win_errstr(result)));
4841                 TALLOC_FREE(r->out.info);
4842                 return result;
4843         }
4844
4845         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4846                                                r->out.info, r->in.level);
4847         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4848
4849         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4850 }
4851
4852 /********************************************************************
4853  ********************************************************************/
4854
4855 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4856         do { \
4857                 if (in && strlen(in)) { \
4858                         out = talloc_strdup(mem_ctx, in); \
4859                 } else { \
4860                         out = talloc_strdup(mem_ctx, ""); \
4861                 } \
4862                 W_ERROR_HAVE_NO_MEMORY(out); \
4863         } while (0);
4864
4865 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4866         do { \
4867                 if (in && strlen(in)) { \
4868                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4869                 } else { \
4870                         out = talloc_strdup(mem_ctx, ""); \
4871                 } \
4872                 W_ERROR_HAVE_NO_MEMORY(out); \
4873         } while (0);
4874
4875 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4876                                                   const char **string_array,
4877                                                   const char ***presult,
4878                                                   const char *cservername,
4879                                                   const char *arch,
4880                                                   int version)
4881 {
4882         int i, num_strings = 0;
4883         const char **array = NULL;
4884
4885         if (string_array == NULL) {
4886                 return WERR_INVALID_PARAMETER;
4887         }
4888
4889         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4890                 const char *str = NULL;
4891
4892                 if (cservername == NULL || arch == NULL) {
4893                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4894                 } else {
4895                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4896                 }
4897
4898                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4899                         TALLOC_FREE(array);
4900                         return WERR_NOMEM;
4901                 }
4902         }
4903
4904         if (i > 0) {
4905                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4906                              &array, &num_strings);
4907         }
4908
4909         if (presult) {
4910                 *presult = array;
4911         }
4912
4913         return WERR_OK;
4914 }
4915
4916 /********************************************************************
4917  * fill a spoolss_DriverInfo1 struct
4918  ********************************************************************/
4919
4920 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4921                                         struct spoolss_DriverInfo1 *r,
4922                                         const struct spoolss_DriverInfo8 *driver,
4923                                         const char *servername)
4924 {
4925         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4926         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4927
4928         return WERR_OK;
4929 }
4930
4931 /********************************************************************
4932  * fill a spoolss_DriverInfo2 struct
4933  ********************************************************************/
4934
4935 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4936                                         struct spoolss_DriverInfo2 *r,
4937                                         const struct spoolss_DriverInfo8 *driver,
4938                                         const char *servername)
4939
4940 {
4941         const char *cservername = canon_servername(servername);
4942
4943         r->version              = driver->version;
4944
4945         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4946         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4947         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4948         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4949
4950         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4951                                driver->architecture,
4952                                driver->version,
4953                                driver->driver_path,
4954                                r->driver_path);
4955
4956         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4957                                driver->architecture,
4958                                driver->version,
4959                                driver->data_file,
4960                                r->data_file);
4961
4962         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4963                                driver->architecture,
4964                                driver->version,
4965                                driver->config_file,
4966                                r->config_file);
4967
4968         return WERR_OK;
4969 }
4970
4971 /********************************************************************
4972  * fill a spoolss_DriverInfo3 struct
4973  ********************************************************************/
4974
4975 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4976                                         struct spoolss_DriverInfo3 *r,
4977                                         const struct spoolss_DriverInfo8 *driver,
4978                                         const char *servername)
4979 {
4980         const char *cservername = canon_servername(servername);
4981
4982         r->version              = driver->version;
4983
4984         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4985         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4986         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4987         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4988
4989         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4990                                driver->architecture,
4991                                driver->version,
4992                                driver->driver_path,
4993                                r->driver_path);
4994
4995         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4996                                driver->architecture,
4997                                driver->version,
4998                                driver->data_file,
4999                                r->data_file);
5000
5001         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5002                                driver->architecture,
5003                                driver->version,
5004                                driver->config_file,
5005                                r->config_file);
5006
5007         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5008                                driver->architecture,
5009                                driver->version,
5010                                driver->help_file,
5011                                r->help_file);
5012
5013         FILL_DRIVER_STRING(mem_ctx,
5014                            driver->monitor_name,
5015                            r->monitor_name);
5016
5017         FILL_DRIVER_STRING(mem_ctx,
5018                            driver->default_datatype,
5019                            r->default_datatype);
5020
5021         return string_array_from_driver_info(mem_ctx,
5022                                              driver->dependent_files,
5023                                              &r->dependent_files,
5024                                              cservername,
5025                                              driver->architecture,
5026                                              driver->version);
5027 }
5028
5029 /********************************************************************
5030  * fill a spoolss_DriverInfo4 struct
5031  ********************************************************************/
5032
5033 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5034                                         struct spoolss_DriverInfo4 *r,
5035                                         const struct spoolss_DriverInfo8 *driver,
5036                                         const char *servername)
5037 {
5038         const char *cservername = canon_servername(servername);
5039         WERROR result;
5040
5041         r->version              = driver->version;
5042
5043         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5044         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5045         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5046         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5047
5048         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5049                                driver->architecture,
5050                                driver->version,
5051                                driver->driver_path,
5052                                r->driver_path);
5053
5054         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5055                                driver->architecture,
5056                                driver->version,
5057                                driver->data_file,
5058                                r->data_file);
5059
5060         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5061                                driver->architecture,
5062                                driver->version,
5063                                driver->config_file,
5064                                r->config_file);
5065
5066         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5067                                driver->architecture,
5068                                driver->version,
5069                                driver->help_file,
5070                                r->help_file);
5071
5072         result = string_array_from_driver_info(mem_ctx,
5073                                                driver->dependent_files,
5074                                                &r->dependent_files,
5075                                                cservername,
5076                                                driver->architecture,
5077                                                driver->version);
5078         if (!W_ERROR_IS_OK(result)) {
5079                 return result;
5080         }
5081
5082         FILL_DRIVER_STRING(mem_ctx,
5083                            driver->monitor_name,
5084                            r->monitor_name);
5085
5086         FILL_DRIVER_STRING(mem_ctx,
5087                            driver->default_datatype,
5088                            r->default_datatype);
5089
5090
5091         result = string_array_from_driver_info(mem_ctx,
5092                                                driver->previous_names,
5093                                                &r->previous_names,
5094                                                NULL, NULL, 0);
5095
5096         return result;
5097 }
5098
5099 /********************************************************************
5100  * fill a spoolss_DriverInfo5 struct
5101  ********************************************************************/
5102
5103 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5104                                         struct spoolss_DriverInfo5 *r,
5105                                         const struct spoolss_DriverInfo8 *driver,
5106                                         const char *servername)
5107 {
5108         const char *cservername = canon_servername(servername);
5109
5110         r->version              = driver->version;
5111
5112         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5113         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5114         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5115         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5116
5117         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5118                                driver->architecture,
5119                                driver->version,
5120                                driver->driver_path,
5121                                r->driver_path);
5122
5123         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5124                                driver->architecture,
5125                                driver->version,
5126                                driver->data_file,
5127                                r->data_file);
5128
5129         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5130                                driver->architecture,
5131                                driver->version,
5132                                driver->config_file,
5133                                r->config_file);
5134
5135         r->driver_attributes    = 0;
5136         r->config_version       = 0;
5137         r->driver_version       = 0;
5138
5139         return WERR_OK;
5140 }
5141 /********************************************************************
5142  * fill a spoolss_DriverInfo6 struct
5143  ********************************************************************/
5144
5145 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5146                                         struct spoolss_DriverInfo6 *r,
5147                                         const struct spoolss_DriverInfo8 *driver,
5148                                         const char *servername)
5149 {
5150         const char *cservername = canon_servername(servername);
5151         WERROR result;
5152
5153         r->version              = driver->version;
5154
5155         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5156         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5157         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5158         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5159
5160         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5161                                driver->architecture,
5162                                driver->version,
5163                                driver->driver_path,
5164                                r->driver_path);
5165
5166         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5167                                driver->architecture,
5168                                driver->version,
5169                                driver->data_file,
5170                                r->data_file);
5171
5172         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5173                                driver->architecture,
5174                                driver->version,
5175                                driver->config_file,
5176                                r->config_file);
5177
5178         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5179                                driver->architecture,
5180                                driver->version,
5181                                driver->help_file,
5182                                r->help_file);
5183
5184         FILL_DRIVER_STRING(mem_ctx,
5185                            driver->monitor_name,
5186                            r->monitor_name);
5187
5188         FILL_DRIVER_STRING(mem_ctx,
5189                            driver->default_datatype,
5190                            r->default_datatype);
5191
5192         result = string_array_from_driver_info(mem_ctx,
5193                                                driver->dependent_files,
5194                                                &r->dependent_files,
5195                                                cservername,
5196                                                driver->architecture,
5197                                                driver->version);
5198         if (!W_ERROR_IS_OK(result)) {
5199                 return result;
5200         }
5201
5202         result = string_array_from_driver_info(mem_ctx,
5203                                                driver->previous_names,
5204                                                &r->previous_names,
5205                                                NULL, NULL, 0);
5206         if (!W_ERROR_IS_OK(result)) {
5207                 return result;
5208         }
5209
5210         r->driver_date          = driver->driver_date;
5211         r->driver_version       = driver->driver_version;
5212
5213         FILL_DRIVER_STRING(mem_ctx,
5214                            driver->manufacturer_name,
5215                            r->manufacturer_name);
5216         FILL_DRIVER_STRING(mem_ctx,
5217                            driver->manufacturer_url,
5218                            r->manufacturer_url);
5219         FILL_DRIVER_STRING(mem_ctx,
5220                            driver->hardware_id,
5221                            r->hardware_id);
5222         FILL_DRIVER_STRING(mem_ctx,
5223                            driver->provider,
5224                            r->provider);
5225
5226         return WERR_OK;
5227 }
5228
5229 /********************************************************************
5230  * fill a spoolss_DriverInfo8 struct
5231  ********************************************************************/
5232
5233 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5234                                         struct spoolss_DriverInfo8 *r,
5235                                         const struct spoolss_DriverInfo8 *driver,
5236                                         const char *servername)
5237 {
5238         const char *cservername = canon_servername(servername);
5239         WERROR result;
5240
5241         r->version              = driver->version;
5242
5243         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5244         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5245         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5246         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5247
5248         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5249                                driver->architecture,
5250                                driver->version,
5251                                driver->driver_path,
5252                                r->driver_path);
5253
5254         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5255                                driver->architecture,
5256                                driver->version,
5257                                driver->data_file,
5258                                r->data_file);
5259
5260         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5261                                driver->architecture,
5262                                driver->version,
5263                                driver->config_file,
5264                                r->config_file);
5265
5266         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5267                                driver->architecture,
5268                                driver->version,
5269                                driver->help_file,
5270                                r->help_file);
5271
5272         FILL_DRIVER_STRING(mem_ctx,
5273                            driver->monitor_name,
5274                            r->monitor_name);
5275
5276         FILL_DRIVER_STRING(mem_ctx,
5277                            driver->default_datatype,
5278                            r->default_datatype);
5279
5280         result = string_array_from_driver_info(mem_ctx,
5281                                                driver->dependent_files,
5282                                                &r->dependent_files,
5283                                                cservername,
5284                                                driver->architecture,
5285                                                driver->version);
5286         if (!W_ERROR_IS_OK(result)) {
5287                 return result;
5288         }
5289
5290         result = string_array_from_driver_info(mem_ctx,
5291                                                driver->previous_names,
5292                                                &r->previous_names,
5293                                                NULL, NULL, 0);
5294         if (!W_ERROR_IS_OK(result)) {
5295                 return result;
5296         }
5297
5298         r->driver_date          = driver->driver_date;
5299         r->driver_version       = driver->driver_version;
5300
5301         FILL_DRIVER_STRING(mem_ctx,
5302                            driver->manufacturer_name,
5303                            r->manufacturer_name);
5304         FILL_DRIVER_STRING(mem_ctx,
5305                            driver->manufacturer_url,
5306                            r->manufacturer_url);
5307         FILL_DRIVER_STRING(mem_ctx,
5308                            driver->hardware_id,
5309                            r->hardware_id);
5310         FILL_DRIVER_STRING(mem_ctx,
5311                            driver->provider,
5312                            r->provider);
5313
5314         FILL_DRIVER_STRING(mem_ctx,
5315                            driver->print_processor,
5316                            r->print_processor);
5317         FILL_DRIVER_STRING(mem_ctx,
5318                            driver->vendor_setup,
5319                            r->vendor_setup);
5320
5321         result = string_array_from_driver_info(mem_ctx,
5322                                                driver->color_profiles,
5323                                                &r->color_profiles,
5324                                                NULL, NULL, 0);
5325         if (!W_ERROR_IS_OK(result)) {
5326                 return result;
5327         }
5328
5329         FILL_DRIVER_STRING(mem_ctx,
5330                            driver->inf_path,
5331                            r->inf_path);
5332
5333         r->printer_driver_attributes    = driver->printer_driver_attributes;
5334
5335         result = string_array_from_driver_info(mem_ctx,
5336                                                driver->core_driver_dependencies,
5337                                                &r->core_driver_dependencies,
5338                                                NULL, NULL, 0);
5339         if (!W_ERROR_IS_OK(result)) {
5340                 return result;
5341         }
5342
5343         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5344         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5345
5346         return WERR_OK;
5347 }
5348
5349 #if 0 /* disabled until marshalling issues are resolved - gd */
5350 /********************************************************************
5351  ********************************************************************/
5352
5353 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5354                                           struct spoolss_DriverFileInfo *r,
5355                                           const char *cservername,
5356                                           const char *file_name,
5357                                           enum spoolss_DriverFileType file_type,
5358                                           uint32_t file_version)
5359 {
5360         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5361                                           cservername, file_name);
5362         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5363         r->file_type    = file_type;
5364         r->file_version = file_version;
5365
5366         return WERR_OK;
5367 }
5368
5369 /********************************************************************
5370  ********************************************************************/
5371
5372 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5373                                                  const struct spoolss_DriverInfo8 *driver,
5374                                                  const char *cservername,
5375                                                  struct spoolss_DriverFileInfo **info_p,
5376                                                  uint32_t *count_p)
5377 {
5378         struct spoolss_DriverFileInfo *info = NULL;
5379         uint32_t count = 0;
5380         WERROR result;
5381         uint32_t i;
5382
5383         *info_p = NULL;
5384         *count_p = 0;
5385
5386         if (strlen(driver->driver_path)) {
5387                 info = talloc_realloc(mem_ctx, info,
5388                                             struct spoolss_DriverFileInfo,
5389                                             count + 1);
5390                 W_ERROR_HAVE_NO_MEMORY(info);
5391                 result = fill_spoolss_DriverFileInfo(info,
5392                                                      &info[count],
5393                                                      cservername,
5394                                                      driver->driver_path,
5395                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5396                                                      0);
5397                 W_ERROR_NOT_OK_RETURN(result);
5398                 count++;
5399         }
5400
5401         if (strlen(driver->config_file)) {
5402                 info = talloc_realloc(mem_ctx, info,
5403                                             struct spoolss_DriverFileInfo,
5404                                             count + 1);
5405                 W_ERROR_HAVE_NO_MEMORY(info);
5406                 result = fill_spoolss_DriverFileInfo(info,
5407                                                      &info[count],
5408                                                      cservername,
5409                                                      driver->config_file,
5410                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5411                                                      0);
5412                 W_ERROR_NOT_OK_RETURN(result);
5413                 count++;
5414         }
5415
5416         if (strlen(driver->data_file)) {
5417                 info = talloc_realloc(mem_ctx, info,
5418                                             struct spoolss_DriverFileInfo,
5419                                             count + 1);
5420                 W_ERROR_HAVE_NO_MEMORY(info);
5421                 result = fill_spoolss_DriverFileInfo(info,
5422                                                      &info[count],
5423                                                      cservername,
5424                                                      driver->data_file,
5425                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5426                                                      0);
5427                 W_ERROR_NOT_OK_RETURN(result);
5428                 count++;
5429         }
5430
5431         if (strlen(driver->help_file)) {
5432                 info = talloc_realloc(mem_ctx, info,
5433                                             struct spoolss_DriverFileInfo,
5434                                             count + 1);
5435                 W_ERROR_HAVE_NO_MEMORY(info);
5436                 result = fill_spoolss_DriverFileInfo(info,
5437                                                      &info[count],
5438                                                      cservername,
5439                                                      driver->help_file,
5440                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5441                                                      0);
5442                 W_ERROR_NOT_OK_RETURN(result);
5443                 count++;
5444         }
5445
5446         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5447                 info = talloc_realloc(mem_ctx, info,
5448                                             struct spoolss_DriverFileInfo,
5449                                             count + 1);
5450                 W_ERROR_HAVE_NO_MEMORY(info);
5451                 result = fill_spoolss_DriverFileInfo(info,
5452                                                      &info[count],
5453                                                      cservername,
5454                                                      driver->dependent_files[i],
5455                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5456                                                      0);
5457                 W_ERROR_NOT_OK_RETURN(result);
5458                 count++;
5459         }
5460
5461         *info_p = info;
5462         *count_p = count;
5463
5464         return WERR_OK;
5465 }
5466
5467 /********************************************************************
5468  * fill a spoolss_DriverInfo101 struct
5469  ********************************************************************/
5470
5471 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5472                                           struct spoolss_DriverInfo101 *r,
5473                                           const struct spoolss_DriverInfo8 *driver,
5474                                           const char *servername)
5475 {
5476         const char *cservername = canon_servername(servername);
5477         WERROR result;
5478
5479         r->version              = driver->version;
5480
5481         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5482         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5483         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5484         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5485
5486         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5487                                                     cservername,
5488                                                     &r->file_info,
5489                                                     &r->file_count);
5490         if (!W_ERROR_IS_OK(result)) {
5491                 return result;
5492         }
5493
5494         FILL_DRIVER_STRING(mem_ctx,
5495                            driver->monitor_name,
5496                            r->monitor_name);
5497
5498         FILL_DRIVER_STRING(mem_ctx,
5499                            driver->default_datatype,
5500                            r->default_datatype);
5501
5502         result = string_array_from_driver_info(mem_ctx,
5503                                                driver->previous_names,
5504                                                &r->previous_names,
5505                                                NULL, NULL, 0);
5506         if (!W_ERROR_IS_OK(result)) {
5507                 return result;
5508         }
5509
5510         r->driver_date          = driver->driver_date;
5511         r->driver_version       = driver->driver_version;
5512
5513         FILL_DRIVER_STRING(mem_ctx,
5514                            driver->manufacturer_name,
5515                            r->manufacturer_name);
5516         FILL_DRIVER_STRING(mem_ctx,
5517                            driver->manufacturer_url,
5518                            r->manufacturer_url);
5519         FILL_DRIVER_STRING(mem_ctx,
5520                            driver->hardware_id,
5521                            r->hardware_id);
5522         FILL_DRIVER_STRING(mem_ctx,
5523                            driver->provider,
5524                            r->provider);
5525
5526         return WERR_OK;
5527 }
5528 #endif
5529 /********************************************************************
5530  ********************************************************************/
5531
5532 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5533                                                   const struct auth_session_info *session_info,
5534                                                   struct messaging_context *msg_ctx,
5535                                                   uint32_t level,
5536                                                   union spoolss_DriverInfo *r,
5537                                                   int snum,
5538                                                   const char *servername,
5539                                                   const char *architecture,
5540                                                   uint32_t version)
5541 {
5542         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5543         struct spoolss_DriverInfo8 *driver;
5544         WERROR result;
5545         struct dcerpc_binding_handle *b;
5546         TALLOC_CTX *tmp_ctx = NULL;
5547
5548         if (level == 101) {
5549                 return WERR_UNKNOWN_LEVEL;
5550         }
5551
5552         tmp_ctx = talloc_new(mem_ctx);
5553         if (!tmp_ctx) {
5554                 return WERR_NOMEM;
5555         }
5556
5557         result = winreg_printer_binding_handle(tmp_ctx,
5558                                                session_info,
5559                                                msg_ctx,
5560                                                &b);
5561         if (!W_ERROR_IS_OK(result)) {
5562                 goto done;
5563         }
5564
5565         result = winreg_get_printer(tmp_ctx, b,
5566                                     lp_const_servicename(snum),
5567                                     &pinfo2);
5568
5569         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5570                 win_errstr(result)));
5571
5572         if (!W_ERROR_IS_OK(result)) {
5573                 result = WERR_INVALID_PRINTER_NAME;
5574                 goto done;
5575         }
5576
5577         result = winreg_get_driver(tmp_ctx, b,
5578                                    architecture,
5579                                    pinfo2->drivername, version, &driver);
5580
5581         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5582                 win_errstr(result)));
5583
5584         if (!W_ERROR_IS_OK(result)) {
5585                 /*
5586                  * Is this a W2k client ?
5587                  */
5588
5589                 if (version < 3) {
5590                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5591                         goto done;
5592                 }
5593
5594                 /* Yes - try again with a WinNT driver. */
5595                 version = 2;
5596                 result = winreg_get_driver(tmp_ctx, b,
5597                                            architecture,
5598                                            pinfo2->drivername,
5599                                            version, &driver);
5600                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5601                         win_errstr(result)));
5602                 if (!W_ERROR_IS_OK(result)) {
5603                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5604                         goto done;
5605                 }
5606         }
5607
5608         /* these are allocated on mem_ctx and not tmp_ctx because they are
5609          * the 'return value' and need to utlive this call */
5610         switch (level) {
5611         case 1:
5612                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5613                 break;
5614         case 2:
5615                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5616                 break;
5617         case 3:
5618                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5619                 break;
5620         case 4:
5621                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5622                 break;
5623         case 5:
5624                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5625                 break;
5626         case 6:
5627                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5628                 break;
5629         case 8:
5630                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5631                 break;
5632 #if 0 /* disabled until marshalling issues are resolved - gd */
5633         case 101:
5634                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5635                 break;
5636 #endif
5637         default:
5638                 result = WERR_UNKNOWN_LEVEL;
5639                 break;
5640         }
5641
5642 done:
5643         talloc_free(tmp_ctx);
5644         return result;
5645 }
5646
5647 /****************************************************************
5648  _spoolss_GetPrinterDriver2
5649 ****************************************************************/
5650
5651 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5652                                   struct spoolss_GetPrinterDriver2 *r)
5653 {
5654         struct printer_handle *printer;
5655         WERROR result;
5656
5657         int snum;
5658
5659         /* that's an [in out] buffer */
5660
5661         if (!r->in.buffer && (r->in.offered != 0)) {
5662                 return WERR_INVALID_PARAM;
5663         }
5664
5665         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5666
5667         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5668                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5669                 return WERR_INVALID_PRINTER_NAME;
5670         }
5671
5672         *r->out.needed = 0;
5673         *r->out.server_major_version = 0;
5674         *r->out.server_minor_version = 0;
5675
5676         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5677                 return WERR_BADFID;
5678         }
5679
5680         result = construct_printer_driver_info_level(p->mem_ctx,
5681                                                      get_session_info_system(),
5682                                                      p->msg_ctx,
5683                                                      r->in.level, r->out.info,
5684                                                      snum, printer->servername,
5685                                                      r->in.architecture,
5686                                                      r->in.client_major_version);
5687         if (!W_ERROR_IS_OK(result)) {
5688                 TALLOC_FREE(r->out.info);
5689                 return result;
5690         }
5691
5692         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5693                                                r->out.info, r->in.level);
5694         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5695
5696         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5697 }
5698
5699
5700 /****************************************************************
5701  _spoolss_StartPagePrinter
5702 ****************************************************************/
5703
5704 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5705                                  struct spoolss_StartPagePrinter *r)
5706 {
5707         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5708
5709         if (!Printer) {
5710                 DEBUG(3,("_spoolss_StartPagePrinter: "
5711                         "Error in startpageprinter printer handle\n"));
5712                 return WERR_BADFID;
5713         }
5714
5715         Printer->page_started = true;
5716         return WERR_OK;
5717 }
5718
5719 /****************************************************************
5720  _spoolss_EndPagePrinter
5721 ****************************************************************/
5722
5723 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5724                                struct spoolss_EndPagePrinter *r)
5725 {
5726         int snum;
5727
5728         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5729
5730         if (!Printer) {
5731                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5732                         OUR_HANDLE(r->in.handle)));
5733                 return WERR_BADFID;
5734         }
5735
5736         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5737                 return WERR_BADFID;
5738
5739         Printer->page_started = false;
5740         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5741
5742         return WERR_OK;
5743 }
5744
5745 /****************************************************************
5746  _spoolss_StartDocPrinter
5747 ****************************************************************/
5748
5749 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5750                                 struct spoolss_StartDocPrinter *r)
5751 {
5752         struct spoolss_DocumentInfo1 *info_1;
5753         int snum;
5754         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5755         WERROR werr;
5756         char *rhost;
5757         int rc;
5758
5759         if (!Printer) {
5760                 DEBUG(2,("_spoolss_StartDocPrinter: "
5761                         "Invalid handle (%s:%u:%u)\n",
5762                         OUR_HANDLE(r->in.handle)));
5763                 return WERR_BADFID;
5764         }
5765
5766         if (Printer->jobid) {
5767                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5768                           "StartDocPrinter called twice! "
5769                           "(existing jobid = %d)\n", Printer->jobid));
5770                 return WERR_INVALID_HANDLE;
5771         }
5772
5773         if (r->in.level != 1) {
5774                 return WERR_UNKNOWN_LEVEL;
5775         }
5776
5777         info_1 = r->in.info.info1;
5778
5779         /*
5780          * a nice thing with NT is it doesn't listen to what you tell it.
5781          * when asked to send _only_ RAW datas, it tries to send datas
5782          * in EMF format.
5783          *
5784          * So I add checks like in NT Server ...
5785          */
5786
5787         if (info_1->datatype) {
5788                 if (strcmp(info_1->datatype, "RAW") != 0) {
5789                         *r->out.job_id = 0;
5790                         return WERR_INVALID_DATATYPE;
5791                 }
5792         }
5793
5794         /* get the share number of the printer */
5795         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5796                 return WERR_BADFID;
5797         }
5798
5799         rc = get_remote_hostname(p->remote_address,
5800                                  &rhost,
5801                                  p->mem_ctx);
5802         if (rc < 0) {
5803                 return WERR_NOMEM;
5804         }
5805         if (strequal(rhost,"UNKNOWN")) {
5806                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5807                                                          p->mem_ctx);
5808                 if (rhost == NULL) {
5809                         return WERR_NOMEM;
5810                 }
5811         }
5812
5813         werr = print_job_start(p->session_info,
5814                                p->msg_ctx,
5815                                rhost,
5816                                snum,
5817                                info_1->document_name,
5818                                info_1->output_file,
5819                                Printer->devmode,
5820                                &Printer->jobid);
5821
5822         /* An error occured in print_job_start() so return an appropriate
5823            NT error code. */
5824
5825         if (!W_ERROR_IS_OK(werr)) {
5826                 return werr;
5827         }
5828
5829         Printer->document_started = true;
5830         *r->out.job_id = Printer->jobid;
5831
5832         return WERR_OK;
5833 }
5834
5835 /****************************************************************
5836  _spoolss_EndDocPrinter
5837 ****************************************************************/
5838
5839 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5840                               struct spoolss_EndDocPrinter *r)
5841 {
5842         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5843         NTSTATUS status;
5844         int snum;
5845
5846         if (!Printer) {
5847                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5848                         OUR_HANDLE(r->in.handle)));
5849                 return WERR_BADFID;
5850         }
5851
5852         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5853                 return WERR_BADFID;
5854         }
5855
5856         Printer->document_started = false;
5857         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5858         if (!NT_STATUS_IS_OK(status)) {
5859                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5860                           "print_job_end failed [%s]\n",
5861                           nt_errstr(status)));
5862         }
5863
5864         Printer->jobid = 0;
5865         return ntstatus_to_werror(status);
5866 }
5867
5868 /****************************************************************
5869  _spoolss_WritePrinter
5870 ****************************************************************/
5871
5872 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5873                              struct spoolss_WritePrinter *r)
5874 {
5875         ssize_t buffer_written;
5876         int snum;
5877         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5878
5879         if (!Printer) {
5880                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5881                         OUR_HANDLE(r->in.handle)));
5882                 *r->out.num_written = r->in._data_size;
5883                 return WERR_BADFID;
5884         }
5885
5886         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5887                 return WERR_BADFID;
5888
5889         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5890         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5891                                                    snum, Printer->jobid,
5892                                                    (const char *)r->in.data.data,
5893                                                    (size_t)r->in._data_size);
5894         if (buffer_written == (ssize_t)-1) {
5895                 *r->out.num_written = 0;
5896                 if (errno == ENOSPC)
5897                         return WERR_NO_SPOOL_SPACE;
5898                 else
5899                         return WERR_ACCESS_DENIED;
5900         }
5901
5902         *r->out.num_written = r->in._data_size;
5903
5904         return WERR_OK;
5905 }
5906
5907 /********************************************************************
5908  * api_spoolss_getprinter
5909  * called from the spoolss dispatcher
5910  *
5911  ********************************************************************/
5912
5913 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5914                               struct pipes_struct *p)
5915 {
5916         const struct auth_session_info *session_info = p->session_info;
5917         int snum;
5918         WERROR errcode = WERR_BADFUNC;
5919         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5920
5921         if (!Printer) {
5922                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5923                         OUR_HANDLE(handle)));
5924                 return WERR_BADFID;
5925         }
5926
5927         if (!get_printer_snum(p, handle, &snum, NULL))
5928                 return WERR_BADFID;
5929
5930         switch (command) {
5931         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5932                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5933                 break;
5934         case SPOOLSS_PRINTER_CONTROL_RESUME:
5935         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5936                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5937                 break;
5938         case SPOOLSS_PRINTER_CONTROL_PURGE:
5939                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5940                 break;
5941         default:
5942                 return WERR_UNKNOWN_LEVEL;
5943         }
5944
5945         return errcode;
5946 }
5947
5948
5949 /****************************************************************
5950  _spoolss_AbortPrinter
5951  * From MSDN: "Deletes printer's spool file if printer is configured
5952  * for spooling"
5953 ****************************************************************/
5954
5955 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5956                              struct spoolss_AbortPrinter *r)
5957 {
5958         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5959         int             snum;
5960         WERROR          errcode = WERR_OK;
5961
5962         if (!Printer) {
5963                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5964                         OUR_HANDLE(r->in.handle)));
5965                 return WERR_BADFID;
5966         }
5967
5968         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5969                 return WERR_BADFID;
5970
5971         if (!Printer->document_started) {
5972                 return WERR_SPL_NO_STARTDOC;
5973         }
5974
5975         errcode = print_job_delete(p->session_info,
5976                                    p->msg_ctx,
5977                                    snum,
5978                                    Printer->jobid);
5979
5980         return errcode;
5981 }
5982
5983 /********************************************************************
5984  * called by spoolss_api_setprinter
5985  * when updating a printer description
5986  ********************************************************************/
5987
5988 static WERROR update_printer_sec(struct policy_handle *handle,
5989                                  struct pipes_struct *p,
5990                                  struct sec_desc_buf *secdesc_ctr)
5991 {
5992         struct spoolss_security_descriptor *new_secdesc = NULL;
5993         struct spoolss_security_descriptor *old_secdesc = NULL;
5994         const char *printer;
5995         WERROR result;
5996         int snum;
5997         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5998         struct dcerpc_binding_handle *b;
5999         TALLOC_CTX *tmp_ctx = NULL;
6000
6001         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6002                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6003                          OUR_HANDLE(handle)));
6004
6005                 result = WERR_BADFID;
6006                 goto done;
6007         }
6008
6009         if (secdesc_ctr == NULL) {
6010                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6011                 result = WERR_INVALID_PARAM;
6012                 goto done;
6013         }
6014         printer = lp_const_servicename(snum);
6015
6016         /* Check the user has permissions to change the security
6017            descriptor.  By experimentation with two NT machines, the user
6018            requires Full Access to the printer to change security
6019            information. */
6020
6021         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6022                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6023                 result = WERR_ACCESS_DENIED;
6024                 goto done;
6025         }
6026
6027         tmp_ctx = talloc_new(p->mem_ctx);
6028         if (!tmp_ctx) {
6029                 return WERR_NOMEM;
6030         }
6031
6032         result = winreg_printer_binding_handle(tmp_ctx,
6033                                                get_session_info_system(),
6034                                                p->msg_ctx,
6035                                                &b);
6036         if (!W_ERROR_IS_OK(result)) {
6037                 goto done;
6038         }
6039
6040         /* NT seems to like setting the security descriptor even though
6041            nothing may have actually changed. */
6042         result = winreg_get_printer_secdesc(tmp_ctx, b,
6043                                             printer,
6044                                             &old_secdesc);
6045         if (!W_ERROR_IS_OK(result)) {
6046                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6047                 result = WERR_BADFID;
6048                 goto done;
6049         }
6050
6051         if (DEBUGLEVEL >= 10) {
6052                 struct security_acl *the_acl;
6053                 int i;
6054
6055                 the_acl = old_secdesc->dacl;
6056                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6057                            printer, the_acl->num_aces));
6058
6059                 for (i = 0; i < the_acl->num_aces; i++) {
6060                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6061                                            &the_acl->aces[i].trustee),
6062                                   the_acl->aces[i].access_mask));
6063                 }
6064
6065                 the_acl = secdesc_ctr->sd->dacl;
6066
6067                 if (the_acl) {
6068                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6069                                    printer, the_acl->num_aces));
6070
6071                         for (i = 0; i < the_acl->num_aces; i++) {
6072                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6073                                                    &the_acl->aces[i].trustee),
6074                                            the_acl->aces[i].access_mask));
6075                         }
6076                 } else {
6077                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6078                 }
6079         }
6080
6081         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6082         if (new_secdesc == NULL) {
6083                 result = WERR_NOMEM;
6084                 goto done;
6085         }
6086
6087         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6088                 result = WERR_OK;
6089                 goto done;
6090         }
6091
6092         result = winreg_set_printer_secdesc(tmp_ctx, b,
6093                                             printer,
6094                                             new_secdesc);
6095
6096 done:
6097         talloc_free(tmp_ctx);
6098         return result;
6099 }
6100
6101 /********************************************************************
6102  Canonicalize printer info from a client
6103  ********************************************************************/
6104
6105 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6106                              struct spoolss_SetPrinterInfo2 *info2,
6107                              int snum)
6108 {
6109         fstring printername;
6110         const char *p;
6111
6112         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6113                 "portname=%s drivername=%s comment=%s location=%s\n",
6114                 info2->servername, info2->printername, info2->sharename,
6115                 info2->portname, info2->drivername, info2->comment,
6116                 info2->location));
6117
6118         /* we force some elements to "correct" values */
6119         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6120         if (info2->servername == NULL) {
6121                 return false;
6122         }
6123         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6124         if (info2->sharename == NULL) {
6125                 return false;
6126         }
6127
6128         /* check to see if we allow printername != sharename */
6129         if (lp_force_printername(snum)) {
6130                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6131                                         lp_netbios_name(), info2->sharename);
6132         } else {
6133                 /* make sure printername is in \\server\printername format */
6134                 fstrcpy(printername, info2->printername);
6135                 p = printername;
6136                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6137                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6138                                 p++;
6139                 }
6140
6141                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6142                                         lp_netbios_name(), p);
6143         }
6144         if (info2->printername == NULL) {
6145                 return false;
6146         }
6147
6148         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6149         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6150
6151         return true;
6152 }
6153
6154 /****************************************************************************
6155 ****************************************************************************/
6156
6157 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6158 {
6159         char *cmd = lp_addport_cmd();
6160         char *command = NULL;
6161         int ret;
6162         bool is_print_op = false;
6163
6164         if ( !*cmd ) {
6165                 return WERR_ACCESS_DENIED;
6166         }
6167
6168         command = talloc_asprintf(ctx,
6169                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6170         if (!command) {
6171                 return WERR_NOMEM;
6172         }
6173
6174         if ( token )
6175                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6176
6177         DEBUG(10,("Running [%s]\n", command));
6178
6179         /********* BEGIN SePrintOperatorPrivilege **********/
6180
6181         if ( is_print_op )
6182                 become_root();
6183
6184         ret = smbrun(command, NULL);
6185
6186         if ( is_print_op )
6187                 unbecome_root();
6188
6189         /********* END SePrintOperatorPrivilege **********/
6190
6191         DEBUGADD(10,("returned [%d]\n", ret));
6192
6193         TALLOC_FREE(command);
6194
6195         if ( ret != 0 ) {
6196                 return WERR_ACCESS_DENIED;
6197         }
6198
6199         return WERR_OK;
6200 }
6201
6202 /****************************************************************************
6203 ****************************************************************************/
6204
6205 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6206                                    int snum)
6207 {
6208         /*
6209          * As we do not know if we are embedded in the file server process
6210          * or not, we have to pretend that all shares are in use.
6211          */
6212         return true;
6213 }
6214
6215 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6216                              struct spoolss_SetPrinterInfo2 *info2,
6217                              const char *remote_machine,
6218                              struct messaging_context *msg_ctx)
6219 {
6220         char *cmd = lp_addprinter_cmd();
6221         char **qlines;
6222         char *command = NULL;
6223         int numlines;
6224         int ret;
6225         int fd;
6226         bool is_print_op = false;
6227
6228         if (!remote_machine) {
6229                 return false;
6230         }
6231
6232         command = talloc_asprintf(ctx,
6233                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6234                         cmd, info2->printername, info2->sharename,
6235                         info2->portname, info2->drivername,
6236                         info2->location, info2->comment, remote_machine);
6237         if (!command) {
6238                 return false;
6239         }
6240
6241         if ( token )
6242                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6243
6244         DEBUG(10,("Running [%s]\n", command));
6245
6246         /********* BEGIN SePrintOperatorPrivilege **********/
6247
6248         if ( is_print_op )
6249                 become_root();
6250
6251         if ( (ret = smbrun(command, &fd)) == 0 ) {
6252                 /* Tell everyone we updated smb.conf. */
6253                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6254         }
6255
6256         if ( is_print_op )
6257                 unbecome_root();
6258
6259         /********* END SePrintOperatorPrivilege **********/
6260
6261         DEBUGADD(10,("returned [%d]\n", ret));
6262
6263         TALLOC_FREE(command);
6264
6265         if ( ret != 0 ) {
6266                 if (fd != -1)
6267                         close(fd);
6268                 return false;
6269         }
6270
6271         /* reload our services immediately */
6272         become_root();
6273         reload_services(NULL, spoolss_conn_snum_used, false);
6274         unbecome_root();
6275
6276         numlines = 0;
6277         /* Get lines and convert them back to dos-codepage */
6278         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6279         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6280         close(fd);
6281
6282         /* Set the portname to what the script says the portname should be. */
6283         /* but don't require anything to be return from the script exit a good error code */
6284
6285         if (numlines) {
6286                 /* Set the portname to what the script says the portname should be. */
6287                 info2->portname = talloc_strdup(ctx, qlines[0]);
6288                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6289         }
6290
6291         TALLOC_FREE(qlines);
6292         return true;
6293 }
6294
6295 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6296                                const struct auth_session_info *session_info,
6297                                struct messaging_context *msg_ctx,
6298                                int snum,
6299                                struct spoolss_SetPrinterInfo2 *printer,
6300                                struct spoolss_PrinterInfo2 *old_printer)
6301 {
6302         bool force_update = (old_printer == NULL);
6303         const char *dnsdomname;
6304         const char *longname;
6305         const char *uncname;
6306         const char *spooling;
6307         DATA_BLOB buffer;
6308         WERROR result = WERR_OK;
6309         struct dcerpc_binding_handle *b;
6310         TALLOC_CTX *tmp_ctx;
6311
6312         tmp_ctx = talloc_new(mem_ctx);
6313         if (!tmp_ctx) {
6314                 return WERR_NOMEM;
6315         }
6316
6317         result = winreg_printer_binding_handle(tmp_ctx,
6318                                                session_info,
6319                                                msg_ctx,
6320                                                &b);
6321         if (!W_ERROR_IS_OK(result)) {
6322                 goto done;
6323         }
6324
6325         if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6326                 push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6327                 winreg_set_printer_dataex(tmp_ctx, b,
6328                                           printer->sharename,
6329                                           SPOOL_DSSPOOLER_KEY,
6330                                           SPOOL_REG_DRIVERNAME,
6331                                           REG_SZ,
6332                                           buffer.data,
6333                                           buffer.length);
6334
6335                 if (!force_update) {
6336                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6337                                 printer->drivername));
6338
6339                         notify_printer_driver(server_event_context(), msg_ctx,
6340                                               snum, printer->drivername ?
6341                                               printer->drivername : "");
6342                 }
6343         }
6344
6345         if (force_update || !strequal(printer->comment, old_printer->comment)) {
6346                 push_reg_sz(tmp_ctx, &buffer, printer->comment);
6347                 winreg_set_printer_dataex(tmp_ctx, b,
6348                                           printer->sharename,
6349                                           SPOOL_DSSPOOLER_KEY,
6350                                           SPOOL_REG_DESCRIPTION,
6351                                           REG_SZ,
6352                                           buffer.data,
6353                                           buffer.length);
6354
6355                 if (!force_update) {
6356                         notify_printer_comment(server_event_context(), msg_ctx,
6357                                                snum, printer->comment ?
6358                                                printer->comment : "");
6359                 }
6360         }
6361
6362         if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6363                 push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6364                 winreg_set_printer_dataex(tmp_ctx, b,
6365                                           printer->sharename,
6366                                           SPOOL_DSSPOOLER_KEY,
6367                                           SPOOL_REG_PRINTSHARENAME,
6368                                           REG_SZ,
6369                                           buffer.data,
6370                                           buffer.length);
6371
6372                 if (!force_update) {
6373                         notify_printer_sharename(server_event_context(),
6374                                                  msg_ctx,
6375                                                  snum, printer->sharename ?
6376                                                  printer->sharename : "");
6377                 }
6378         }
6379
6380         if (force_update || !strequal(printer->printername, old_printer->printername)) {
6381                 const char *p;
6382
6383                 p = strrchr(printer->printername, '\\' );
6384                 if (p != NULL) {
6385                         p++;
6386                 } else {
6387                         p = printer->printername;
6388                 }
6389
6390                 push_reg_sz(tmp_ctx, &buffer, p);
6391                 winreg_set_printer_dataex(tmp_ctx, b,
6392                                           printer->sharename,
6393                                           SPOOL_DSSPOOLER_KEY,
6394                                           SPOOL_REG_PRINTERNAME,
6395                                           REG_SZ,
6396                                           buffer.data,
6397                                           buffer.length);
6398
6399                 if (!force_update) {
6400                         notify_printer_printername(server_event_context(),
6401                                                    msg_ctx, snum, p ? p : "");
6402                 }
6403         }
6404
6405         if (force_update || !strequal(printer->portname, old_printer->portname)) {
6406                 push_reg_sz(tmp_ctx, &buffer, printer->portname);
6407                 winreg_set_printer_dataex(tmp_ctx, b,
6408                                           printer->sharename,
6409                                           SPOOL_DSSPOOLER_KEY,
6410                                           SPOOL_REG_PORTNAME,
6411                                           REG_SZ,
6412                                           buffer.data,
6413                                           buffer.length);
6414
6415                 if (!force_update) {
6416                         notify_printer_port(server_event_context(),
6417                                             msg_ctx, snum, printer->portname ?
6418                                             printer->portname : "");
6419                 }
6420         }
6421
6422         if (force_update || !strequal(printer->location, old_printer->location)) {
6423                 push_reg_sz(tmp_ctx, &buffer, printer->location);
6424                 winreg_set_printer_dataex(tmp_ctx, b,
6425                                           printer->sharename,
6426                                           SPOOL_DSSPOOLER_KEY,
6427                                           SPOOL_REG_LOCATION,
6428                                           REG_SZ,
6429                                           buffer.data,
6430                                           buffer.length);
6431
6432                 if (!force_update) {
6433                         notify_printer_location(server_event_context(),
6434                                                 msg_ctx, snum,
6435                                                 printer->location ?
6436                                                 printer->location : "");
6437                 }
6438         }
6439
6440         if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6441                 push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6442                 winreg_set_printer_dataex(tmp_ctx, b,
6443                                           printer->sharename,
6444                                           SPOOL_DSSPOOLER_KEY,
6445                                           SPOOL_REG_PRINTSEPARATORFILE,
6446                                           REG_SZ,
6447                                           buffer.data,
6448                                           buffer.length);
6449
6450                 if (!force_update) {
6451                         notify_printer_sepfile(server_event_context(),
6452                                                msg_ctx, snum,
6453                                                printer->sepfile ?
6454                                                printer->sepfile : "");
6455                 }
6456         }
6457
6458         if (force_update || printer->starttime != old_printer->starttime) {
6459                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6460                 SIVAL(buffer.data, 0, printer->starttime);
6461                 winreg_set_printer_dataex(tmp_ctx, b,
6462                                           printer->sharename,
6463                                           SPOOL_DSSPOOLER_KEY,
6464                                           SPOOL_REG_PRINTSTARTTIME,
6465                                           REG_DWORD,
6466                                           buffer.data,
6467                                           buffer.length);
6468         }
6469
6470         if (force_update || printer->untiltime != old_printer->untiltime) {
6471                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6472                 SIVAL(buffer.data, 0, printer->untiltime);
6473                 winreg_set_printer_dataex(tmp_ctx, b,
6474                                           printer->sharename,
6475                                           SPOOL_DSSPOOLER_KEY,
6476                                           SPOOL_REG_PRINTENDTIME,
6477                                           REG_DWORD,
6478                                           buffer.data,
6479                                           buffer.length);
6480         }
6481
6482         if (force_update || printer->priority != old_printer->priority) {
6483                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6484                 SIVAL(buffer.data, 0, printer->priority);
6485                 winreg_set_printer_dataex(tmp_ctx, b,
6486                                           printer->sharename,
6487                                           SPOOL_DSSPOOLER_KEY,
6488                                           SPOOL_REG_PRIORITY,
6489                                           REG_DWORD,
6490                                           buffer.data,
6491                                           buffer.length);
6492         }
6493
6494         if (force_update || printer->attributes != old_printer->attributes) {
6495                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6496                 SIVAL(buffer.data, 0, (printer->attributes &
6497                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6498                 winreg_set_printer_dataex(tmp_ctx, b,
6499                                           printer->sharename,
6500                                           SPOOL_DSSPOOLER_KEY,
6501                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6502                                           REG_DWORD,
6503                                           buffer.data,
6504                                           buffer.length);
6505
6506                 switch (printer->attributes & 0x3) {
6507                         case 0:
6508                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6509                                 break;
6510                         case 1:
6511                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6512                                 break;
6513                         case 2:
6514                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6515                                 break;
6516                         default:
6517                                 spooling = "unknown";
6518                 }
6519                 push_reg_sz(tmp_ctx, &buffer, spooling);
6520                 winreg_set_printer_dataex(tmp_ctx, b,
6521                                           printer->sharename,
6522                                           SPOOL_DSSPOOLER_KEY,
6523                                           SPOOL_REG_PRINTSPOOLING,
6524                                           REG_SZ,
6525                                           buffer.data,
6526                                           buffer.length);
6527         }
6528
6529         push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6530         winreg_set_printer_dataex(tmp_ctx, b,
6531                                   printer->sharename,
6532                                   SPOOL_DSSPOOLER_KEY,
6533                                   SPOOL_REG_SHORTSERVERNAME,
6534                                   REG_SZ,
6535                                   buffer.data,
6536                                   buffer.length);
6537
6538         dnsdomname = get_mydnsfullname();
6539         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6540                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6541         } else {
6542                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6543         }
6544         if (longname == NULL) {
6545                 result = WERR_NOMEM;
6546                 goto done;
6547         }
6548
6549         push_reg_sz(tmp_ctx, &buffer, longname);
6550         winreg_set_printer_dataex(tmp_ctx, b,
6551                                   printer->sharename,
6552                                   SPOOL_DSSPOOLER_KEY,
6553                                   SPOOL_REG_SERVERNAME,
6554                                   REG_SZ,
6555                                   buffer.data,
6556                                   buffer.length);
6557
6558         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6559                                   lp_netbios_name(), printer->sharename);
6560         push_reg_sz(tmp_ctx, &buffer, uncname);
6561         winreg_set_printer_dataex(tmp_ctx, b,
6562                                   printer->sharename,
6563                                   SPOOL_DSSPOOLER_KEY,
6564                                   SPOOL_REG_UNCNAME,
6565                                   REG_SZ,
6566                                   buffer.data,
6567                                   buffer.length);
6568
6569 done:
6570         talloc_free(tmp_ctx);
6571         return result;
6572 }
6573
6574 /********************************************************************
6575  * Called by spoolss_api_setprinter
6576  * when updating a printer description.
6577  ********************************************************************/
6578
6579 static WERROR update_printer(struct pipes_struct *p,
6580                              struct policy_handle *handle,
6581                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6582                              struct spoolss_DeviceMode *devmode)
6583 {
6584         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6585         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6586         struct spoolss_PrinterInfo2 *old_printer;
6587         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6588         int snum;
6589         WERROR result = WERR_OK;
6590         TALLOC_CTX *tmp_ctx;
6591         struct dcerpc_binding_handle *b;
6592
6593         DEBUG(8,("update_printer\n"));
6594
6595         tmp_ctx = talloc_new(p->mem_ctx);
6596         if (tmp_ctx == NULL) {
6597                 return WERR_NOMEM;
6598         }
6599
6600         if (!Printer) {
6601                 result = WERR_BADFID;
6602                 goto done;
6603         }
6604
6605         if (!get_printer_snum(p, handle, &snum, NULL)) {
6606                 result = WERR_BADFID;
6607                 goto done;
6608         }
6609
6610         result = winreg_printer_binding_handle(tmp_ctx,
6611                                                get_session_info_system(),
6612                                                p->msg_ctx,
6613                                                &b);
6614         if (!W_ERROR_IS_OK(result)) {
6615                 goto done;
6616         }
6617
6618         result = winreg_get_printer(tmp_ctx, b,
6619                                     lp_const_servicename(snum),
6620                                     &old_printer);
6621         if (!W_ERROR_IS_OK(result)) {
6622                 result = WERR_BADFID;
6623                 goto done;
6624         }
6625
6626         /* Do sanity check on the requested changes for Samba */
6627         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6628                 result = WERR_INVALID_PARAM;
6629                 goto done;
6630         }
6631
6632         /* FIXME!!! If the driver has changed we really should verify that
6633            it is installed before doing much else   --jerry */
6634
6635         /* Check calling user has permission to update printer description */
6636         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6637                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6638                 result = WERR_ACCESS_DENIED;
6639                 goto done;
6640         }
6641
6642         /* Call addprinter hook */
6643         /* Check changes to see if this is really needed */
6644
6645         if (*lp_addprinter_cmd() &&
6646                         (!strequal(printer->drivername, old_printer->drivername) ||
6647                          !strequal(printer->comment, old_printer->comment) ||
6648                          !strequal(printer->portname, old_printer->portname) ||
6649                          !strequal(printer->location, old_printer->location)) )
6650         {
6651                 char *raddr;
6652
6653                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6654                                                          p->mem_ctx);
6655                 if (raddr == NULL) {
6656                         return WERR_NOMEM;
6657                 }
6658
6659                 /* add_printer_hook() will call reload_services() */
6660                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6661                                       printer, raddr,
6662                                       p->msg_ctx)) {
6663                         result = WERR_ACCESS_DENIED;
6664                         goto done;
6665                 }
6666         }
6667
6668         update_dsspooler(tmp_ctx,
6669                          get_session_info_system(),
6670                          p->msg_ctx,
6671                          snum,
6672                          printer,
6673                          old_printer);
6674
6675         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6676
6677         if (devmode == NULL) {
6678                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6679         }
6680         result = winreg_update_printer(tmp_ctx, b,
6681                                        printer->sharename,
6682                                        printer_mask,
6683                                        printer,
6684                                        devmode,
6685                                        NULL);
6686
6687 done:
6688         talloc_free(tmp_ctx);
6689
6690         return result;
6691 }
6692
6693 /****************************************************************************
6694 ****************************************************************************/
6695 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6696                                            struct policy_handle *handle,
6697                                            struct spoolss_SetPrinterInfo7 *info7)
6698 {
6699 #ifdef HAVE_ADS
6700         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6701         WERROR result;
6702         int snum;
6703         struct printer_handle *Printer;
6704
6705         if ( lp_security() != SEC_ADS ) {
6706                 return WERR_UNKNOWN_LEVEL;
6707         }
6708
6709         Printer = find_printer_index_by_hnd(p, handle);
6710
6711         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6712
6713         if (!Printer)
6714                 return WERR_BADFID;
6715
6716         if (!get_printer_snum(p, handle, &snum, NULL))
6717                 return WERR_BADFID;
6718
6719         result = winreg_get_printer_internal(p->mem_ctx,
6720                                     get_session_info_system(),
6721                                     p->msg_ctx,
6722                                     lp_servicename(snum),
6723                                     &pinfo2);
6724         if (!W_ERROR_IS_OK(result)) {
6725                 return WERR_BADFID;
6726         }
6727
6728         nt_printer_publish(pinfo2,
6729                            get_session_info_system(),
6730                            p->msg_ctx,
6731                            pinfo2,
6732                            info7->action);
6733
6734         TALLOC_FREE(pinfo2);
6735         return WERR_OK;
6736 #else
6737         return WERR_UNKNOWN_LEVEL;
6738 #endif
6739 }
6740
6741 /********************************************************************
6742  ********************************************************************/
6743
6744 static WERROR update_printer_devmode(struct pipes_struct *p,
6745                                      struct policy_handle *handle,
6746                                      struct spoolss_DeviceMode *devmode)
6747 {
6748         int snum;
6749         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6750         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6751
6752         DEBUG(8,("update_printer_devmode\n"));
6753
6754         if (!Printer) {
6755                 return WERR_BADFID;
6756         }
6757
6758         if (!get_printer_snum(p, handle, &snum, NULL)) {
6759                 return WERR_BADFID;
6760         }
6761
6762         /* Check calling user has permission to update printer description */
6763         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6764                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6765                 return WERR_ACCESS_DENIED;
6766         }
6767
6768         return winreg_update_printer_internal(p->mem_ctx,
6769                                      get_session_info_system(),
6770                                      p->msg_ctx,
6771                                      lp_const_servicename(snum),
6772                                      info2_mask,
6773                                      NULL,
6774                                      devmode,
6775                                      NULL);
6776 }
6777
6778
6779 /****************************************************************
6780  _spoolss_SetPrinter
6781 ****************************************************************/
6782
6783 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6784                            struct spoolss_SetPrinter *r)
6785 {
6786         WERROR result;
6787
6788         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6789
6790         if (!Printer) {
6791                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6792                         OUR_HANDLE(r->in.handle)));
6793                 return WERR_BADFID;
6794         }
6795
6796         /* check the level */
6797         switch (r->in.info_ctr->level) {
6798                 case 0:
6799                         return control_printer(r->in.handle, r->in.command, p);
6800                 case 2:
6801                         result = update_printer(p, r->in.handle,
6802                                                 r->in.info_ctr,
6803                                                 r->in.devmode_ctr->devmode);
6804                         if (!W_ERROR_IS_OK(result))
6805                                 return result;
6806                         if (r->in.secdesc_ctr->sd)
6807                                 result = update_printer_sec(r->in.handle, p,
6808                                                             r->in.secdesc_ctr);
6809                         return result;
6810                 case 3:
6811                         return update_printer_sec(r->in.handle, p,
6812                                                   r->in.secdesc_ctr);
6813                 case 7:
6814                         return publish_or_unpublish_printer(p, r->in.handle,
6815                                                             r->in.info_ctr->info.info7);
6816                 case 8:
6817                         return update_printer_devmode(p, r->in.handle,
6818                                                       r->in.devmode_ctr->devmode);
6819                 default:
6820                         return WERR_UNKNOWN_LEVEL;
6821         }
6822 }
6823
6824 /****************************************************************
6825  _spoolss_FindClosePrinterNotify
6826 ****************************************************************/
6827
6828 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6829                                        struct spoolss_FindClosePrinterNotify *r)
6830 {
6831         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6832
6833         if (!Printer) {
6834                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6835                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6836                 return WERR_BADFID;
6837         }
6838
6839         if (Printer->notify.cli_chan != NULL &&
6840             Printer->notify.cli_chan->active_connections > 0) {
6841                 int snum = -1;
6842
6843                 if (Printer->printer_type == SPLHND_PRINTER) {
6844                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6845                                 return WERR_BADFID;
6846                         }
6847                 }
6848
6849                 srv_spoolss_replycloseprinter(snum, Printer);
6850         }
6851
6852         Printer->notify.flags=0;
6853         Printer->notify.options=0;
6854         Printer->notify.localmachine[0]='\0';
6855         Printer->notify.printerlocal=0;
6856         TALLOC_FREE(Printer->notify.option);
6857
6858         return WERR_OK;
6859 }
6860
6861 /****************************************************************
6862  _spoolss_AddJob
6863 ****************************************************************/
6864
6865 WERROR _spoolss_AddJob(struct pipes_struct *p,
6866                        struct spoolss_AddJob *r)
6867 {
6868         if (!r->in.buffer && (r->in.offered != 0)) {
6869                 return WERR_INVALID_PARAM;
6870         }
6871
6872         /* this is what a NT server returns for AddJob. AddJob must fail on
6873          * non-local printers */
6874
6875         if (r->in.level != 1) {
6876                 return WERR_UNKNOWN_LEVEL;
6877         }
6878
6879         return WERR_INVALID_PARAM;
6880 }
6881
6882 /****************************************************************************
6883 fill_job_info1
6884 ****************************************************************************/
6885
6886 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6887                              struct spoolss_JobInfo1 *r,
6888                              const print_queue_struct *queue,
6889                              int position, int snum,
6890                              struct spoolss_PrinterInfo2 *pinfo2)
6891 {
6892         struct tm *t;
6893
6894         t = gmtime(&queue->time);
6895
6896         r->job_id               = queue->job;
6897
6898         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6899         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6900         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6901         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6902         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6903         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6904         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6905         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6906         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6907         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6908         r->text_status          = talloc_strdup(mem_ctx, "");
6909         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6910
6911         r->status               = nt_printj_status(queue->status);
6912         r->priority             = queue->priority;
6913         r->position             = position;
6914         r->total_pages          = queue->page_count;
6915         r->pages_printed        = 0; /* ??? */
6916
6917         init_systemtime(&r->submitted, t);
6918
6919         return WERR_OK;
6920 }
6921
6922 /****************************************************************************
6923 fill_job_info2
6924 ****************************************************************************/
6925
6926 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6927                              struct spoolss_JobInfo2 *r,
6928                              const print_queue_struct *queue,
6929                              int position, int snum,
6930                              struct spoolss_PrinterInfo2 *pinfo2,
6931                              struct spoolss_DeviceMode *devmode)
6932 {
6933         struct tm *t;
6934
6935         t = gmtime(&queue->time);
6936
6937         r->job_id               = queue->job;
6938
6939         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6940         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6941         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6942         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6943         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6944         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6945         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6946         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6947         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
6948         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6949         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6950         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6951         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
6952         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6953         r->parameters           = talloc_strdup(mem_ctx, "");
6954         W_ERROR_HAVE_NO_MEMORY(r->parameters);
6955         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
6956         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6957
6958         r->devmode              = devmode;
6959
6960         r->text_status          = talloc_strdup(mem_ctx, "");
6961         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6962
6963         r->secdesc              = NULL;
6964
6965         r->status               = nt_printj_status(queue->status);
6966         r->priority             = queue->priority;
6967         r->position             = position;
6968         r->start_time           = 0;
6969         r->until_time           = 0;
6970         r->total_pages          = queue->page_count;
6971         r->size                 = queue->size;
6972         init_systemtime(&r->submitted, t);
6973         r->time                 = 0;
6974         r->pages_printed        = 0; /* ??? */
6975
6976         return WERR_OK;
6977 }
6978
6979 /****************************************************************************
6980 fill_job_info3
6981 ****************************************************************************/
6982
6983 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6984                              struct spoolss_JobInfo3 *r,
6985                              const print_queue_struct *queue,
6986                              const print_queue_struct *next_queue,
6987                              int position, int snum,
6988                              struct spoolss_PrinterInfo2 *pinfo2)
6989 {
6990         r->job_id               = queue->job;
6991         r->next_job_id          = 0;
6992         if (next_queue) {
6993                 r->next_job_id  = next_queue->job;
6994         }
6995         r->reserved             = 0;
6996
6997         return WERR_OK;
6998 }
6999
7000 /****************************************************************************
7001  Enumjobs at level 1.
7002 ****************************************************************************/
7003
7004 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7005                               const print_queue_struct *queue,
7006                               uint32_t num_queues, int snum,
7007                               struct spoolss_PrinterInfo2 *pinfo2,
7008                               union spoolss_JobInfo **info_p,
7009                               uint32_t *count)
7010 {
7011         union spoolss_JobInfo *info;
7012         int i;
7013         WERROR result = WERR_OK;
7014
7015         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7016         W_ERROR_HAVE_NO_MEMORY(info);
7017
7018         *count = num_queues;
7019
7020         for (i=0; i<*count; i++) {
7021                 result = fill_job_info1(info,
7022                                         &info[i].info1,
7023                                         &queue[i],
7024                                         i,
7025                                         snum,
7026                                         pinfo2);
7027                 if (!W_ERROR_IS_OK(result)) {
7028                         goto out;
7029                 }
7030         }
7031
7032  out:
7033         if (!W_ERROR_IS_OK(result)) {
7034                 TALLOC_FREE(info);
7035                 *count = 0;
7036                 return result;
7037         }
7038
7039         *info_p = info;
7040
7041         return WERR_OK;
7042 }
7043
7044 /****************************************************************************
7045  Enumjobs at level 2.
7046 ****************************************************************************/
7047
7048 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7049                               const print_queue_struct *queue,
7050                               uint32_t num_queues, int snum,
7051                               struct spoolss_PrinterInfo2 *pinfo2,
7052                               union spoolss_JobInfo **info_p,
7053                               uint32_t *count)
7054 {
7055         union spoolss_JobInfo *info;
7056         int i;
7057         WERROR result = WERR_OK;
7058
7059         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7060         W_ERROR_HAVE_NO_MEMORY(info);
7061
7062         *count = num_queues;
7063
7064         for (i=0; i<*count; i++) {
7065                 struct spoolss_DeviceMode *devmode;
7066
7067                 result = spoolss_create_default_devmode(info,
7068                                                         pinfo2->printername,
7069                                                         &devmode);
7070                 if (!W_ERROR_IS_OK(result)) {
7071                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7072                         goto out;
7073                 }
7074
7075                 result = fill_job_info2(info,
7076                                         &info[i].info2,
7077                                         &queue[i],
7078                                         i,
7079                                         snum,
7080                                         pinfo2,
7081                                         devmode);
7082                 if (!W_ERROR_IS_OK(result)) {
7083                         goto out;
7084                 }
7085         }
7086
7087  out:
7088         if (!W_ERROR_IS_OK(result)) {
7089                 TALLOC_FREE(info);
7090                 *count = 0;
7091                 return result;
7092         }
7093
7094         *info_p = info;
7095
7096         return WERR_OK;
7097 }
7098
7099 /****************************************************************************
7100  Enumjobs at level 3.
7101 ****************************************************************************/
7102
7103 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7104                               const print_queue_struct *queue,
7105                               uint32_t num_queues, int snum,
7106                               struct spoolss_PrinterInfo2 *pinfo2,
7107                               union spoolss_JobInfo **info_p,
7108                               uint32_t *count)
7109 {
7110         union spoolss_JobInfo *info;
7111         int i;
7112         WERROR result = WERR_OK;
7113
7114         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7115         W_ERROR_HAVE_NO_MEMORY(info);
7116
7117         *count = num_queues;
7118
7119         for (i=0; i<*count; i++) {
7120                 const print_queue_struct *next_queue = NULL;
7121
7122                 if (i+1 < *count) {
7123                         next_queue = &queue[i+1];
7124                 }
7125
7126                 result = fill_job_info3(info,
7127                                         &info[i].info3,
7128                                         &queue[i],
7129                                         next_queue,
7130                                         i,
7131                                         snum,
7132                                         pinfo2);
7133                 if (!W_ERROR_IS_OK(result)) {
7134                         goto out;
7135                 }
7136         }
7137
7138  out:
7139         if (!W_ERROR_IS_OK(result)) {
7140                 TALLOC_FREE(info);
7141                 *count = 0;
7142                 return result;
7143         }
7144
7145         *info_p = info;
7146
7147         return WERR_OK;
7148 }
7149
7150 /****************************************************************
7151  _spoolss_EnumJobs
7152 ****************************************************************/
7153
7154 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7155                          struct spoolss_EnumJobs *r)
7156 {
7157         WERROR result;
7158         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7159         int snum;
7160         print_status_struct prt_status;
7161         print_queue_struct *queue = NULL;
7162         uint32_t count;
7163
7164         /* that's an [in out] buffer */
7165
7166         if (!r->in.buffer && (r->in.offered != 0)) {
7167                 return WERR_INVALID_PARAM;
7168         }
7169
7170         DEBUG(4,("_spoolss_EnumJobs\n"));
7171
7172         *r->out.needed = 0;
7173         *r->out.count = 0;
7174         *r->out.info = NULL;
7175
7176         /* lookup the printer snum and tdb entry */
7177
7178         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7179                 return WERR_BADFID;
7180         }
7181
7182         result = winreg_get_printer_internal(p->mem_ctx,
7183                                     get_session_info_system(),
7184                                     p->msg_ctx,
7185                                     lp_const_servicename(snum),
7186                                     &pinfo2);
7187         if (!W_ERROR_IS_OK(result)) {
7188                 return result;
7189         }
7190
7191         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7192         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7193                 count, prt_status.status, prt_status.message));
7194
7195         if (count == 0) {
7196                 SAFE_FREE(queue);
7197                 TALLOC_FREE(pinfo2);
7198                 return WERR_OK;
7199         }
7200
7201         switch (r->in.level) {
7202         case 1:
7203                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7204                                          pinfo2, r->out.info, r->out.count);
7205                 break;
7206         case 2:
7207                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7208                                          pinfo2, r->out.info, r->out.count);
7209                 break;
7210         case 3:
7211                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7212                                          pinfo2, r->out.info, r->out.count);
7213                 break;
7214         default:
7215                 result = WERR_UNKNOWN_LEVEL;
7216                 break;
7217         }
7218
7219         SAFE_FREE(queue);
7220         TALLOC_FREE(pinfo2);
7221
7222         if (!W_ERROR_IS_OK(result)) {
7223                 return result;
7224         }
7225
7226         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7227                                                      spoolss_EnumJobs,
7228                                                      *r->out.info, r->in.level,
7229                                                      *r->out.count);
7230         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7231         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7232
7233         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7234 }
7235
7236 /****************************************************************
7237  _spoolss_ScheduleJob
7238 ****************************************************************/
7239
7240 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7241                             struct spoolss_ScheduleJob *r)
7242 {
7243         return WERR_OK;
7244 }
7245
7246 /****************************************************************
7247 ****************************************************************/
7248
7249 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7250                                struct messaging_context *msg_ctx,
7251                                const char *printer_name,
7252                                uint32_t job_id,
7253                                struct spoolss_SetJobInfo1 *r)
7254 {
7255         char *old_doc_name;
7256
7257         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7258                 return WERR_BADFID;
7259         }
7260
7261         if (strequal(old_doc_name, r->document_name)) {
7262                 return WERR_OK;
7263         }
7264
7265         if (!print_job_set_name(server_event_context(), msg_ctx,
7266                                 printer_name, job_id, r->document_name)) {
7267                 return WERR_BADFID;
7268         }
7269
7270         return WERR_OK;
7271 }
7272
7273 /****************************************************************
7274  _spoolss_SetJob
7275 ****************************************************************/
7276
7277 WERROR _spoolss_SetJob(struct pipes_struct *p,
7278                        struct spoolss_SetJob *r)
7279 {
7280         const struct auth_session_info *session_info = p->session_info;
7281         int snum;
7282         WERROR errcode = WERR_BADFUNC;
7283
7284         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7285                 return WERR_BADFID;
7286         }
7287
7288         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7289                 return WERR_INVALID_PRINTER_NAME;
7290         }
7291
7292         switch (r->in.command) {
7293         case SPOOLSS_JOB_CONTROL_CANCEL:
7294         case SPOOLSS_JOB_CONTROL_DELETE:
7295                 errcode = print_job_delete(session_info, p->msg_ctx,
7296                                            snum, r->in.job_id);
7297                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7298                         errcode = WERR_OK;
7299                 }
7300                 break;
7301         case SPOOLSS_JOB_CONTROL_PAUSE:
7302                 if (print_job_pause(session_info, p->msg_ctx,
7303                                     snum, r->in.job_id, &errcode)) {
7304                         errcode = WERR_OK;
7305                 }
7306                 break;
7307         case SPOOLSS_JOB_CONTROL_RESTART:
7308         case SPOOLSS_JOB_CONTROL_RESUME:
7309                 if (print_job_resume(session_info, p->msg_ctx,
7310                                      snum, r->in.job_id, &errcode)) {
7311                         errcode = WERR_OK;
7312                 }
7313                 break;
7314         case 0:
7315                 errcode = WERR_OK;
7316                 break;
7317         default:
7318                 return WERR_UNKNOWN_LEVEL;
7319         }
7320
7321         if (!W_ERROR_IS_OK(errcode)) {
7322                 return errcode;
7323         }
7324
7325         if (r->in.ctr == NULL) {
7326                 return errcode;
7327         }
7328
7329         switch (r->in.ctr->level) {
7330         case 1:
7331                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7332                                            lp_const_servicename(snum),
7333                                            r->in.job_id,
7334                                            r->in.ctr->info.info1);
7335                 break;
7336         case 2:
7337         case 3:
7338         case 4:
7339         default:
7340                 return WERR_UNKNOWN_LEVEL;
7341         }
7342
7343         return errcode;
7344 }
7345
7346 /****************************************************************************
7347  Enumerates all printer drivers by level and architecture.
7348 ****************************************************************************/
7349
7350 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7351                                                        const struct auth_session_info *session_info,
7352                                                        struct messaging_context *msg_ctx,
7353                                                        const char *servername,
7354                                                        const char *architecture,
7355                                                        uint32_t level,
7356                                                        union spoolss_DriverInfo **info_p,
7357                                                        uint32_t *count_p)
7358 {
7359         int i;
7360         uint32_t version;
7361         struct spoolss_DriverInfo8 *driver;
7362         union spoolss_DriverInfo *info = NULL;
7363         uint32_t count = 0;
7364         WERROR result = WERR_OK;
7365         uint32_t num_drivers;
7366         const char **drivers;
7367         struct dcerpc_binding_handle *b;
7368         TALLOC_CTX *tmp_ctx = NULL;
7369
7370         *count_p = 0;
7371         *info_p = NULL;
7372
7373         tmp_ctx = talloc_new(mem_ctx);
7374         if (!tmp_ctx) {
7375                 return WERR_NOMEM;
7376         }
7377
7378         result = winreg_printer_binding_handle(tmp_ctx,
7379                                                session_info,
7380                                                msg_ctx,
7381                                                &b);
7382         if (!W_ERROR_IS_OK(result)) {
7383                 goto out;
7384         }
7385
7386         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7387                 result = winreg_get_driver_list(tmp_ctx, b,
7388                                                 architecture, version,
7389                                                 &num_drivers, &drivers);
7390                 if (!W_ERROR_IS_OK(result)) {
7391                         goto out;
7392                 }
7393                 DEBUG(4, ("we have:[%d] drivers in environment"
7394                           " [%s] and version [%d]\n",
7395                           num_drivers, architecture, version));
7396
7397                 if (num_drivers != 0) {
7398                         info = talloc_realloc(tmp_ctx, info,
7399                                                     union spoolss_DriverInfo,
7400                                                     count + num_drivers);
7401                         if (!info) {
7402                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7403                                         "failed to enlarge driver info buffer!\n"));
7404                                 result = WERR_NOMEM;
7405                                 goto out;
7406                         }
7407                 }
7408
7409                 for (i = 0; i < num_drivers; i++) {
7410                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7411
7412                         result = winreg_get_driver(tmp_ctx, b,
7413                                                    architecture, drivers[i],
7414                                                    version, &driver);
7415                         if (!W_ERROR_IS_OK(result)) {
7416                                 goto out;
7417                         }
7418
7419                         switch (level) {
7420                         case 1:
7421                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7422                                                                    driver, servername);
7423                                 break;
7424                         case 2:
7425                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7426                                                                    driver, servername);
7427                                 break;
7428                         case 3:
7429                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7430                                                                    driver, servername);
7431                                 break;
7432                         case 4:
7433                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7434                                                                    driver, servername);
7435                                 break;
7436                         case 5:
7437                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7438                                                                    driver, servername);
7439                                 break;
7440                         case 6:
7441                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7442                                                                    driver, servername);
7443                                 break;
7444                         case 8:
7445                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7446                                                                    driver, servername);
7447                                 break;
7448                         default:
7449                                 result = WERR_UNKNOWN_LEVEL;
7450                                 break;
7451                         }
7452
7453                         TALLOC_FREE(driver);
7454
7455                         if (!W_ERROR_IS_OK(result)) {
7456                                 goto out;
7457                         }
7458                 }
7459
7460                 count += num_drivers;
7461                 TALLOC_FREE(drivers);
7462         }
7463
7464 out:
7465         if (W_ERROR_IS_OK(result)) {
7466                 *info_p = talloc_move(mem_ctx, &info);
7467                 *count_p = count;
7468         }
7469
7470         talloc_free(tmp_ctx);
7471         return result;
7472 }
7473
7474 /****************************************************************************
7475  Enumerates all printer drivers by level.
7476 ****************************************************************************/
7477
7478 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7479                                        const struct auth_session_info *session_info,
7480                                        struct messaging_context *msg_ctx,
7481                                        const char *servername,
7482                                        const char *architecture,
7483                                        uint32_t level,
7484                                        union spoolss_DriverInfo **info_p,
7485                                        uint32_t *count_p)
7486 {
7487         uint32_t a,i;
7488         WERROR result = WERR_OK;
7489
7490         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7491
7492                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7493
7494                         union spoolss_DriverInfo *info = NULL;
7495                         uint32_t count = 0;
7496
7497                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7498                                                                           session_info,
7499                                                                           msg_ctx,
7500                                                                           servername,
7501                                                                           archi_table[a].long_archi,
7502                                                                           level,
7503                                                                           &info,
7504                                                                           &count);
7505                         if (!W_ERROR_IS_OK(result)) {
7506                                 continue;
7507                         }
7508
7509                         for (i=0; i < count; i++) {
7510                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7511                                              info[i], info_p, count_p);
7512                         }
7513                 }
7514
7515                 return result;
7516         }
7517
7518         return enumprinterdrivers_level_by_architecture(mem_ctx,
7519                                                         session_info,
7520                                                         msg_ctx,
7521                                                         servername,
7522                                                         architecture,
7523                                                         level,
7524                                                         info_p,
7525                                                         count_p);
7526 }
7527
7528 /****************************************************************
7529  _spoolss_EnumPrinterDrivers
7530 ****************************************************************/
7531
7532 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7533                                    struct spoolss_EnumPrinterDrivers *r)
7534 {
7535         const char *cservername;
7536         WERROR result;
7537
7538         /* that's an [in out] buffer */
7539
7540         if (!r->in.buffer && (r->in.offered != 0)) {
7541                 return WERR_INVALID_PARAM;
7542         }
7543
7544         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7545
7546         *r->out.needed = 0;
7547         *r->out.count = 0;
7548         *r->out.info = NULL;
7549
7550         cservername = canon_servername(r->in.server);
7551
7552         if (!is_myname_or_ipaddr(cservername)) {
7553                 return WERR_UNKNOWN_PRINTER_DRIVER;
7554         }
7555
7556         result = enumprinterdrivers_level(p->mem_ctx,
7557                                           get_session_info_system(),
7558                                           p->msg_ctx,
7559                                           cservername,
7560                                           r->in.environment,
7561                                           r->in.level,
7562                                           r->out.info,
7563                                           r->out.count);
7564         if (!W_ERROR_IS_OK(result)) {
7565                 return result;
7566         }
7567
7568         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7569                                                      spoolss_EnumPrinterDrivers,
7570                                                      *r->out.info, r->in.level,
7571                                                      *r->out.count);
7572         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7573         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7574
7575         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7576 }
7577
7578 /****************************************************************
7579  _spoolss_EnumForms
7580 ****************************************************************/
7581
7582 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7583                           struct spoolss_EnumForms *r)
7584 {
7585         WERROR result;
7586
7587         *r->out.count = 0;
7588         *r->out.needed = 0;
7589         *r->out.info = NULL;
7590
7591         /* that's an [in out] buffer */
7592
7593         if (!r->in.buffer && (r->in.offered != 0) ) {
7594                 return WERR_INVALID_PARAM;
7595         }
7596
7597         DEBUG(4,("_spoolss_EnumForms\n"));
7598         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7599         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7600
7601         switch (r->in.level) {
7602         case 1:
7603                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7604                                                    get_session_info_system(),
7605                                                    p->msg_ctx,
7606                                                    r->out.count,
7607                                                    r->out.info);
7608                 break;
7609         default:
7610                 result = WERR_UNKNOWN_LEVEL;
7611                 break;
7612         }
7613
7614         if (!W_ERROR_IS_OK(result)) {
7615                 return result;
7616         }
7617
7618         if (*r->out.count == 0) {
7619                 return WERR_NO_MORE_ITEMS;
7620         }
7621
7622         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7623                                                      spoolss_EnumForms,
7624                                                      *r->out.info, r->in.level,
7625                                                      *r->out.count);
7626         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7627         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7628
7629         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7630 }
7631
7632 /****************************************************************
7633  _spoolss_GetForm
7634 ****************************************************************/
7635
7636 WERROR _spoolss_GetForm(struct pipes_struct *p,
7637                         struct spoolss_GetForm *r)
7638 {
7639         WERROR result;
7640
7641         /* that's an [in out] buffer */
7642
7643         if (!r->in.buffer && (r->in.offered != 0)) {
7644                 return WERR_INVALID_PARAM;
7645         }
7646
7647         DEBUG(4,("_spoolss_GetForm\n"));
7648         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7649         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7650
7651         switch (r->in.level) {
7652         case 1:
7653                 result = winreg_printer_getform1_internal(p->mem_ctx,
7654                                                  get_session_info_system(),
7655                                                  p->msg_ctx,
7656                                                  r->in.form_name,
7657                                                  &r->out.info->info1);
7658                 break;
7659         default:
7660                 result = WERR_UNKNOWN_LEVEL;
7661                 break;
7662         }
7663
7664         if (!W_ERROR_IS_OK(result)) {
7665                 TALLOC_FREE(r->out.info);
7666                 return result;
7667         }
7668
7669         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7670                                                r->out.info, r->in.level);
7671         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7672
7673         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7674 }
7675
7676 /****************************************************************************
7677 ****************************************************************************/
7678
7679 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7680                           struct spoolss_PortInfo1 *r,
7681                           const char *name)
7682 {
7683         r->port_name = talloc_strdup(mem_ctx, name);
7684         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7685
7686         return WERR_OK;
7687 }
7688
7689 /****************************************************************************
7690  TODO: This probably needs distinguish between TCP/IP and Local ports
7691  somehow.
7692 ****************************************************************************/
7693
7694 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7695                           struct spoolss_PortInfo2 *r,
7696                           const char *name)
7697 {
7698         r->port_name = talloc_strdup(mem_ctx, name);
7699         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7700
7701         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7702         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7703
7704         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7705         W_ERROR_HAVE_NO_MEMORY(r->description);
7706
7707         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7708         r->reserved = 0;
7709
7710         return WERR_OK;
7711 }
7712
7713
7714 /****************************************************************************
7715  wrapper around the enumer ports command
7716 ****************************************************************************/
7717
7718 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7719 {
7720         char *cmd = lp_enumports_cmd();
7721         char **qlines = NULL;
7722         char *command = NULL;
7723         int numlines;
7724         int ret;
7725         int fd;
7726
7727         *count = 0;
7728         *lines = NULL;
7729
7730         /* if no hook then just fill in the default port */
7731
7732         if ( !*cmd ) {
7733                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7734                         return WERR_NOMEM;
7735                 }
7736                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7737                         TALLOC_FREE(qlines);
7738                         return WERR_NOMEM;
7739                 }
7740                 qlines[1] = NULL;
7741                 numlines = 1;
7742         }
7743         else {
7744                 /* we have a valid enumport command */
7745
7746                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7747                 if (!command) {
7748                         return WERR_NOMEM;
7749                 }
7750
7751                 DEBUG(10,("Running [%s]\n", command));
7752                 ret = smbrun(command, &fd);
7753                 DEBUG(10,("Returned [%d]\n", ret));
7754                 TALLOC_FREE(command);
7755                 if (ret != 0) {
7756                         if (fd != -1) {
7757                                 close(fd);
7758                         }
7759                         return WERR_ACCESS_DENIED;
7760                 }
7761
7762                 numlines = 0;
7763                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7764                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7765                 close(fd);
7766         }
7767
7768         *count = numlines;
7769         *lines = qlines;
7770
7771         return WERR_OK;
7772 }
7773
7774 /****************************************************************************
7775  enumports level 1.
7776 ****************************************************************************/
7777
7778 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7779                                 union spoolss_PortInfo **info_p,
7780                                 uint32_t *count)
7781 {
7782         union spoolss_PortInfo *info = NULL;
7783         int i=0;
7784         WERROR result = WERR_OK;
7785         char **qlines = NULL;
7786         int numlines = 0;
7787
7788         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7789         if (!W_ERROR_IS_OK(result)) {
7790                 goto out;
7791         }
7792
7793         if (numlines) {
7794                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7795                 if (!info) {
7796                         DEBUG(10,("Returning WERR_NOMEM\n"));
7797                         result = WERR_NOMEM;
7798                         goto out;
7799                 }
7800
7801                 for (i=0; i<numlines; i++) {
7802                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7803                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7804                         if (!W_ERROR_IS_OK(result)) {
7805                                 goto out;
7806                         }
7807                 }
7808         }
7809         TALLOC_FREE(qlines);
7810
7811 out:
7812         if (!W_ERROR_IS_OK(result)) {
7813                 TALLOC_FREE(info);
7814                 TALLOC_FREE(qlines);
7815                 *count = 0;
7816                 *info_p = NULL;
7817                 return result;
7818         }
7819
7820         *info_p = info;
7821         *count = numlines;
7822
7823         return WERR_OK;
7824 }
7825
7826 /****************************************************************************
7827  enumports level 2.
7828 ****************************************************************************/
7829
7830 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7831                                 union spoolss_PortInfo **info_p,
7832                                 uint32_t *count)
7833 {
7834         union spoolss_PortInfo *info = NULL;
7835         int i=0;
7836         WERROR result = WERR_OK;
7837         char **qlines = NULL;
7838         int numlines = 0;
7839
7840         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7841         if (!W_ERROR_IS_OK(result)) {
7842                 goto out;
7843         }
7844
7845         if (numlines) {
7846                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7847                 if (!info) {
7848                         DEBUG(10,("Returning WERR_NOMEM\n"));
7849                         result = WERR_NOMEM;
7850                         goto out;
7851                 }
7852
7853                 for (i=0; i<numlines; i++) {
7854                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7855                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7856                         if (!W_ERROR_IS_OK(result)) {
7857                                 goto out;
7858                         }
7859                 }
7860         }
7861         TALLOC_FREE(qlines);
7862
7863 out:
7864         if (!W_ERROR_IS_OK(result)) {
7865                 TALLOC_FREE(info);
7866                 TALLOC_FREE(qlines);
7867                 *count = 0;
7868                 *info_p = NULL;
7869                 return result;
7870         }
7871
7872         *info_p = info;
7873         *count = numlines;
7874
7875         return WERR_OK;
7876 }
7877
7878 /****************************************************************
7879  _spoolss_EnumPorts
7880 ****************************************************************/
7881
7882 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7883                           struct spoolss_EnumPorts *r)
7884 {
7885         WERROR result;
7886
7887         /* that's an [in out] buffer */
7888
7889         if (!r->in.buffer && (r->in.offered != 0)) {
7890                 return WERR_INVALID_PARAM;
7891         }
7892
7893         DEBUG(4,("_spoolss_EnumPorts\n"));
7894
7895         *r->out.count = 0;
7896         *r->out.needed = 0;
7897         *r->out.info = NULL;
7898
7899         switch (r->in.level) {
7900         case 1:
7901                 result = enumports_level_1(p->mem_ctx, r->out.info,
7902                                            r->out.count);
7903                 break;
7904         case 2:
7905                 result = enumports_level_2(p->mem_ctx, r->out.info,
7906                                            r->out.count);
7907                 break;
7908         default:
7909                 return WERR_UNKNOWN_LEVEL;
7910         }
7911
7912         if (!W_ERROR_IS_OK(result)) {
7913                 return result;
7914         }
7915
7916         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7917                                                      spoolss_EnumPorts,
7918                                                      *r->out.info, r->in.level,
7919                                                      *r->out.count);
7920         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7921         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7922
7923         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7924 }
7925
7926 /****************************************************************************
7927 ****************************************************************************/
7928
7929 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7930                                            const char *server,
7931                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7932                                            struct spoolss_DeviceMode *devmode,
7933                                            struct security_descriptor *secdesc,
7934                                            struct spoolss_UserLevelCtr *user_ctr,
7935                                            struct policy_handle *handle)
7936 {
7937         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7938         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7939         int     snum;
7940         WERROR err = WERR_OK;
7941
7942         /* samba does not have a concept of local, non-shared printers yet, so
7943          * make sure we always setup sharename - gd */
7944         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7945             (info2->printername != NULL && info2->printername[0] != '\0')) {
7946                 DEBUG(5, ("spoolss_addprinterex_level_2: "
7947                         "no sharename has been set, setting printername %s as sharename\n",
7948                         info2->printername));
7949                 info2->sharename = info2->printername;
7950         }
7951
7952         /* check to see if the printer already exists */
7953         if ((snum = print_queue_snum(info2->sharename)) != -1) {
7954                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7955                         info2->sharename));
7956                 return WERR_PRINTER_ALREADY_EXISTS;
7957         }
7958
7959         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7960                 if ((snum = print_queue_snum(info2->printername)) != -1) {
7961                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7962                                 info2->printername));
7963                         return WERR_PRINTER_ALREADY_EXISTS;
7964                 }
7965         }
7966
7967         /* validate printer info struct */
7968         if (!info2->printername || strlen(info2->printername) == 0) {
7969                 return WERR_INVALID_PRINTER_NAME;
7970         }
7971         if (!info2->portname || strlen(info2->portname) == 0) {
7972                 return WERR_UNKNOWN_PORT;
7973         }
7974         if (!info2->drivername || strlen(info2->drivername) == 0) {
7975                 return WERR_UNKNOWN_PRINTER_DRIVER;
7976         }
7977         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7978                 return WERR_UNKNOWN_PRINTPROCESSOR;
7979         }
7980
7981         /* FIXME!!!  smbd should check to see if the driver is installed before
7982            trying to add a printer like this  --jerry */
7983
7984         if (*lp_addprinter_cmd() ) {
7985                 char *raddr;
7986
7987                 raddr = tsocket_address_inet_addr_string(p->remote_address,
7988                                                          p->mem_ctx);
7989                 if (raddr == NULL) {
7990                         return WERR_NOMEM;
7991                 }
7992
7993                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7994                                        info2, raddr,
7995                                        p->msg_ctx) ) {
7996                         return WERR_ACCESS_DENIED;
7997                 }
7998         } else {
7999                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8000                         "smb.conf parameter \"addprinter command\" is defined. This "
8001                         "parameter must exist for this call to succeed\n",
8002                         info2->sharename ));
8003         }
8004
8005         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8006                 return WERR_ACCESS_DENIED;
8007         }
8008
8009         /* you must be a printer admin to add a new printer */
8010         if (!print_access_check(p->session_info,
8011                                 p->msg_ctx,
8012                                 snum,
8013                                 PRINTER_ACCESS_ADMINISTER)) {
8014                 return WERR_ACCESS_DENIED;
8015         }
8016
8017         /*
8018          * Do sanity check on the requested changes for Samba.
8019          */
8020
8021         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8022                 return WERR_INVALID_PARAM;
8023         }
8024
8025         if (devmode == NULL) {
8026                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8027         }
8028
8029         update_dsspooler(p->mem_ctx,
8030                          get_session_info_system(),
8031                          p->msg_ctx,
8032                          0,
8033                          info2,
8034                          NULL);
8035
8036         err = winreg_update_printer_internal(p->mem_ctx,
8037                                     get_session_info_system(),
8038                                     p->msg_ctx,
8039                                     info2->sharename,
8040                                     info2_mask,
8041                                     info2,
8042                                     devmode,
8043                                     secdesc);
8044         if (!W_ERROR_IS_OK(err)) {
8045                 return err;
8046         }
8047
8048         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8049         if (!W_ERROR_IS_OK(err)) {
8050                 /* Handle open failed - remove addition. */
8051                 ZERO_STRUCTP(handle);
8052                 return err;
8053         }
8054
8055         return WERR_OK;
8056 }
8057
8058 /****************************************************************
8059  _spoolss_AddPrinterEx
8060 ****************************************************************/
8061
8062 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8063                              struct spoolss_AddPrinterEx *r)
8064 {
8065         switch (r->in.info_ctr->level) {
8066         case 1:
8067                 /* we don't handle yet */
8068                 /* but I know what to do ... */
8069                 return WERR_UNKNOWN_LEVEL;
8070         case 2:
8071                 return spoolss_addprinterex_level_2(p, r->in.server,
8072                                                     r->in.info_ctr,
8073                                                     r->in.devmode_ctr->devmode,
8074                                                     r->in.secdesc_ctr->sd,
8075                                                     r->in.userlevel_ctr,
8076                                                     r->out.handle);
8077         default:
8078                 return WERR_UNKNOWN_LEVEL;
8079         }
8080 }
8081
8082 /****************************************************************
8083  _spoolss_AddPrinter
8084 ****************************************************************/
8085
8086 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8087                            struct spoolss_AddPrinter *r)
8088 {
8089         struct spoolss_AddPrinterEx a;
8090         struct spoolss_UserLevelCtr userlevel_ctr;
8091
8092         ZERO_STRUCT(userlevel_ctr);
8093
8094         userlevel_ctr.level = 1;
8095
8096         a.in.server             = r->in.server;
8097         a.in.info_ctr           = r->in.info_ctr;
8098         a.in.devmode_ctr        = r->in.devmode_ctr;
8099         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8100         a.in.userlevel_ctr      = &userlevel_ctr;
8101         a.out.handle            = r->out.handle;
8102
8103         return _spoolss_AddPrinterEx(p, &a);
8104 }
8105
8106 /****************************************************************
8107  _spoolss_AddPrinterDriverEx
8108 ****************************************************************/
8109
8110 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8111                                    struct spoolss_AddPrinterDriverEx *r)
8112 {
8113         WERROR err = WERR_OK;
8114         const char *driver_name = NULL;
8115         uint32_t version;
8116         const char *fn;
8117
8118         switch (p->opnum) {
8119                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8120                         fn = "_spoolss_AddPrinterDriver";
8121                         break;
8122                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8123                         fn = "_spoolss_AddPrinterDriverEx";
8124                         break;
8125                 default:
8126                         return WERR_INVALID_PARAM;
8127         }
8128
8129         /*
8130          * we only support the semantics of AddPrinterDriver()
8131          * i.e. only copy files that are newer than existing ones
8132          */
8133
8134         if (r->in.flags == 0) {
8135                 return WERR_INVALID_PARAM;
8136         }
8137
8138         if (r->in.flags != APD_COPY_NEW_FILES) {
8139                 return WERR_ACCESS_DENIED;
8140         }
8141
8142         /* FIXME */
8143         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8144                 /* Clever hack from Martin Zielinski <mz@seh.de>
8145                  * to allow downgrade from level 8 (Vista).
8146                  */
8147                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8148                         r->in.info_ctr->level));
8149                 return WERR_UNKNOWN_LEVEL;
8150         }
8151
8152         DEBUG(5,("Cleaning driver's information\n"));
8153         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8154         if (!W_ERROR_IS_OK(err))
8155                 goto done;
8156
8157         DEBUG(5,("Moving driver to final destination\n"));
8158         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8159         if (!W_ERROR_IS_OK(err)) {
8160                 goto done;
8161         }
8162
8163         err = winreg_add_driver_internal(p->mem_ctx,
8164                                 get_session_info_system(),
8165                                 p->msg_ctx,
8166                                 r->in.info_ctr,
8167                                 &driver_name,
8168                                 &version);
8169         if (!W_ERROR_IS_OK(err)) {
8170                 goto done;
8171         }
8172
8173         /*
8174          * I think this is where he DrvUpgradePrinter() hook would be
8175          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8176          * server.  Right now, we just need to send ourselves a message
8177          * to update each printer bound to this driver.   --jerry
8178          */
8179
8180         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8181                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8182                         fn, driver_name));
8183         }
8184
8185 done:
8186         return err;
8187 }
8188
8189 /****************************************************************
8190  _spoolss_AddPrinterDriver
8191 ****************************************************************/
8192
8193 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8194                                  struct spoolss_AddPrinterDriver *r)
8195 {
8196         struct spoolss_AddPrinterDriverEx a;
8197
8198         switch (r->in.info_ctr->level) {
8199         case 2:
8200         case 3:
8201         case 4:
8202         case 5:
8203                 break;
8204         default:
8205                 return WERR_UNKNOWN_LEVEL;
8206         }
8207
8208         a.in.servername         = r->in.servername;
8209         a.in.info_ctr           = r->in.info_ctr;
8210         a.in.flags              = APD_COPY_NEW_FILES;
8211
8212         return _spoolss_AddPrinterDriverEx(p, &a);
8213 }
8214
8215 /****************************************************************************
8216 ****************************************************************************/
8217
8218 struct _spoolss_paths {
8219         int type;
8220         const char *share;
8221         const char *dir;
8222 };
8223
8224 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8225
8226 static const struct _spoolss_paths spoolss_paths[]= {
8227         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8228         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8229 };
8230
8231 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8232                                           const char *servername,
8233                                           const char *environment,
8234                                           int component,
8235                                           char **path)
8236 {
8237         const char *pservername = NULL;
8238         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8239         const char *short_archi;
8240
8241         *path = NULL;
8242
8243         /* environment may be empty */
8244         if (environment && strlen(environment)) {
8245                 long_archi = environment;
8246         }
8247
8248         /* servername may be empty */
8249         if (servername && strlen(servername)) {
8250                 pservername = canon_servername(servername);
8251
8252                 if (!is_myname_or_ipaddr(pservername)) {
8253                         return WERR_INVALID_PARAM;
8254                 }
8255         }
8256
8257         if (!(short_archi = get_short_archi(long_archi))) {
8258                 return WERR_INVALID_ENVIRONMENT;
8259         }
8260
8261         switch (component) {
8262         case SPOOLSS_PRTPROCS_PATH:
8263         case SPOOLSS_DRIVER_PATH:
8264                 if (pservername) {
8265                         *path = talloc_asprintf(mem_ctx,
8266                                         "\\\\%s\\%s\\%s",
8267                                         pservername,
8268                                         spoolss_paths[component].share,
8269                                         short_archi);
8270                 } else {
8271                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8272                                         SPOOLSS_DEFAULT_SERVER_PATH,
8273                                         spoolss_paths[component].dir,
8274                                         short_archi);
8275                 }
8276                 break;
8277         default:
8278                 return WERR_INVALID_PARAM;
8279         }
8280
8281         if (!*path) {
8282                 return WERR_NOMEM;
8283         }
8284
8285         return WERR_OK;
8286 }
8287
8288 /****************************************************************************
8289 ****************************************************************************/
8290
8291 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8292                                           const char *servername,
8293                                           const char *environment,
8294                                           struct spoolss_DriverDirectoryInfo1 *r)
8295 {
8296         WERROR werr;
8297         char *path = NULL;
8298
8299         werr = compose_spoolss_server_path(mem_ctx,
8300                                            servername,
8301                                            environment,
8302                                            SPOOLSS_DRIVER_PATH,
8303                                            &path);
8304         if (!W_ERROR_IS_OK(werr)) {
8305                 return werr;
8306         }
8307
8308         DEBUG(4,("printer driver directory: [%s]\n", path));
8309
8310         r->directory_name = path;
8311
8312         return WERR_OK;
8313 }
8314
8315 /****************************************************************
8316  _spoolss_GetPrinterDriverDirectory
8317 ****************************************************************/
8318
8319 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8320                                           struct spoolss_GetPrinterDriverDirectory *r)
8321 {
8322         WERROR werror;
8323
8324         /* that's an [in out] buffer */
8325
8326         if (!r->in.buffer && (r->in.offered != 0)) {
8327                 return WERR_INVALID_PARAM;
8328         }
8329
8330         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8331                 r->in.level));
8332
8333         *r->out.needed = 0;
8334
8335         /* r->in.level is ignored */
8336
8337         werror = getprinterdriverdir_level_1(p->mem_ctx,
8338                                              r->in.server,
8339                                              r->in.environment,
8340                                              &r->out.info->info1);
8341         if (!W_ERROR_IS_OK(werror)) {
8342                 TALLOC_FREE(r->out.info);
8343                 return werror;
8344         }
8345
8346         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8347                                                r->out.info, r->in.level);
8348         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8349
8350         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8351 }
8352
8353 /****************************************************************
8354  _spoolss_EnumPrinterData
8355 ****************************************************************/
8356
8357 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8358                                 struct spoolss_EnumPrinterData *r)
8359 {
8360         WERROR result;
8361         struct spoolss_EnumPrinterDataEx r2;
8362         uint32_t count;
8363         struct spoolss_PrinterEnumValues *info, *val = NULL;
8364         uint32_t needed;
8365
8366         r2.in.handle    = r->in.handle;
8367         r2.in.key_name  = "PrinterDriverData";
8368         r2.in.offered   = 0;
8369         r2.out.count    = &count;
8370         r2.out.info     = &info;
8371         r2.out.needed   = &needed;
8372
8373         result = _spoolss_EnumPrinterDataEx(p, &r2);
8374         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8375                 r2.in.offered = needed;
8376                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8377         }
8378         if (!W_ERROR_IS_OK(result)) {
8379                 return result;
8380         }
8381
8382         /*
8383          * The NT machine wants to know the biggest size of value and data
8384          *
8385          * cf: MSDN EnumPrinterData remark section
8386          */
8387
8388         if (!r->in.value_offered && !r->in.data_offered) {
8389                 uint32_t biggest_valuesize = 0;
8390                 uint32_t biggest_datasize = 0;
8391                 int i, name_length;
8392
8393                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8394
8395                 for (i=0; i<count; i++) {
8396
8397                         name_length = strlen(info[i].value_name);
8398                         if (strlen(info[i].value_name) > biggest_valuesize) {
8399                                 biggest_valuesize = name_length;
8400                         }
8401
8402                         if (info[i].data_length > biggest_datasize) {
8403                                 biggest_datasize = info[i].data_length;
8404                         }
8405
8406                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8407                                 biggest_datasize));
8408                 }
8409
8410                 /* the value is an UNICODE string but real_value_size is the length
8411                    in bytes including the trailing 0 */
8412
8413                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8414                 *r->out.data_needed  = biggest_datasize;
8415
8416                 DEBUG(6,("final values: [%d], [%d]\n",
8417                         *r->out.value_needed, *r->out.data_needed));
8418
8419                 return WERR_OK;
8420         }
8421
8422         if (r->in.enum_index < count) {
8423                 val = &info[r->in.enum_index];
8424         }
8425
8426         if (val == NULL) {
8427                 /* out_value should default to "" or else NT4 has
8428                    problems unmarshalling the response */
8429
8430                 if (r->in.value_offered) {
8431                         *r->out.value_needed = 1;
8432                         r->out.value_name = talloc_strdup(r, "");
8433                         if (!r->out.value_name) {
8434                                 return WERR_NOMEM;
8435                         }
8436                 } else {
8437                         r->out.value_name = NULL;
8438                         *r->out.value_needed = 0;
8439                 }
8440
8441                 /* the data is counted in bytes */
8442
8443                 *r->out.data_needed = r->in.data_offered;
8444
8445                 result = WERR_NO_MORE_ITEMS;
8446         } else {
8447                 /*
8448                  * the value is:
8449                  * - counted in bytes in the request
8450                  * - counted in UNICODE chars in the max reply
8451                  * - counted in bytes in the real size
8452                  *
8453                  * take a pause *before* coding not *during* coding
8454                  */
8455
8456                 /* name */
8457                 if (r->in.value_offered) {
8458                         r->out.value_name = talloc_strdup(r, val->value_name);
8459                         if (!r->out.value_name) {
8460                                 return WERR_NOMEM;
8461                         }
8462                         *r->out.value_needed = val->value_name_len;
8463                 } else {
8464                         r->out.value_name = NULL;
8465                         *r->out.value_needed = 0;
8466                 }
8467
8468                 /* type */
8469
8470                 *r->out.type = val->type;
8471
8472                 /* data - counted in bytes */
8473
8474                 /*
8475                  * See the section "Dynamically Typed Query Parameters"
8476                  * in MS-RPRN.
8477                  */
8478
8479                 if (r->out.data && val->data && val->data->data &&
8480                                 val->data_length && r->in.data_offered) {
8481                         memcpy(r->out.data, val->data->data,
8482                                 MIN(val->data_length,r->in.data_offered));
8483                 }
8484
8485                 *r->out.data_needed = val->data_length;
8486
8487                 result = WERR_OK;
8488         }
8489
8490         return result;
8491 }
8492
8493 /****************************************************************
8494  _spoolss_SetPrinterData
8495 ****************************************************************/
8496
8497 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8498                                struct spoolss_SetPrinterData *r)
8499 {
8500         struct spoolss_SetPrinterDataEx r2;
8501
8502         r2.in.handle            = r->in.handle;
8503         r2.in.key_name          = "PrinterDriverData";
8504         r2.in.value_name        = r->in.value_name;
8505         r2.in.type              = r->in.type;
8506         r2.in.data              = r->in.data;
8507         r2.in.offered           = r->in.offered;
8508
8509         return _spoolss_SetPrinterDataEx(p, &r2);
8510 }
8511
8512 /****************************************************************
8513  _spoolss_ResetPrinter
8514 ****************************************************************/
8515
8516 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8517                              struct spoolss_ResetPrinter *r)
8518 {
8519         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8520         int             snum;
8521
8522         DEBUG(5,("_spoolss_ResetPrinter\n"));
8523
8524         /*
8525          * All we do is to check to see if the handle and queue is valid.
8526          * This call really doesn't mean anything to us because we only
8527          * support RAW printing.   --jerry
8528          */
8529
8530         if (!Printer) {
8531                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8532                         OUR_HANDLE(r->in.handle)));
8533                 return WERR_BADFID;
8534         }
8535
8536         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8537                 return WERR_BADFID;
8538
8539
8540         /* blindly return success */
8541         return WERR_OK;
8542 }
8543
8544 /****************************************************************
8545  _spoolss_DeletePrinterData
8546 ****************************************************************/
8547
8548 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8549                                   struct spoolss_DeletePrinterData *r)
8550 {
8551         struct spoolss_DeletePrinterDataEx r2;
8552
8553         r2.in.handle            = r->in.handle;
8554         r2.in.key_name          = "PrinterDriverData";
8555         r2.in.value_name        = r->in.value_name;
8556
8557         return _spoolss_DeletePrinterDataEx(p, &r2);
8558 }
8559
8560 /****************************************************************
8561  _spoolss_AddForm
8562 ****************************************************************/
8563
8564 WERROR _spoolss_AddForm(struct pipes_struct *p,
8565                         struct spoolss_AddForm *r)
8566 {
8567         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8568         int snum = -1;
8569         WERROR status = WERR_OK;
8570         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8571         struct dcerpc_binding_handle *b;
8572         TALLOC_CTX *tmp_ctx = NULL;
8573
8574         DEBUG(5,("_spoolss_AddForm\n"));
8575
8576         if (!Printer) {
8577                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8578                         OUR_HANDLE(r->in.handle)));
8579                 return WERR_BADFID;
8580         }
8581
8582         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8583            and not a printer admin, then fail */
8584
8585         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8586             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8587             !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8588                                           p->session_info->info->domain_name,
8589                                           NULL,
8590                                           p->session_info->security_token,
8591                                           lp_printer_admin(snum))) {
8592                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8593                 return WERR_ACCESS_DENIED;
8594         }
8595
8596         switch (form->flags) {
8597         case SPOOLSS_FORM_USER:
8598         case SPOOLSS_FORM_BUILTIN:
8599         case SPOOLSS_FORM_PRINTER:
8600                 break;
8601         default:
8602                 return WERR_INVALID_PARAM;
8603         }
8604
8605         tmp_ctx = talloc_new(p->mem_ctx);
8606         if (!tmp_ctx) {
8607                 return WERR_NOMEM;
8608         }
8609
8610         status = winreg_printer_binding_handle(tmp_ctx,
8611                                                get_session_info_system(),
8612                                                p->msg_ctx,
8613                                                &b);
8614         if (!W_ERROR_IS_OK(status)) {
8615                 goto done;
8616         }
8617
8618         status = winreg_printer_addform1(tmp_ctx, b, form);
8619         if (!W_ERROR_IS_OK(status)) {
8620                 goto done;
8621         }
8622
8623         /*
8624          * ChangeID must always be set if this is a printer
8625          */
8626         if (Printer->printer_type == SPLHND_PRINTER) {
8627                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8628                         status = WERR_BADFID;
8629                         goto done;
8630                 }
8631
8632                 status = winreg_printer_update_changeid(tmp_ctx, b,
8633                                                         lp_const_servicename(snum));
8634         }
8635
8636 done:
8637         talloc_free(tmp_ctx);
8638         return status;
8639 }
8640
8641 /****************************************************************
8642  _spoolss_DeleteForm
8643 ****************************************************************/
8644
8645 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8646                            struct spoolss_DeleteForm *r)
8647 {
8648         const char *form_name = r->in.form_name;
8649         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8650         int snum = -1;
8651         WERROR status = WERR_OK;
8652         struct dcerpc_binding_handle *b;
8653         TALLOC_CTX *tmp_ctx = NULL;
8654
8655         DEBUG(5,("_spoolss_DeleteForm\n"));
8656
8657         if (!Printer) {
8658                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8659                         OUR_HANDLE(r->in.handle)));
8660                 return WERR_BADFID;
8661         }
8662
8663         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8664             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8665             !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8666                                           p->session_info->info->domain_name,
8667                                           NULL,
8668                                           p->session_info->security_token,
8669                                           lp_printer_admin(snum))) {
8670                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8671                 return WERR_ACCESS_DENIED;
8672         }
8673
8674         tmp_ctx = talloc_new(p->mem_ctx);
8675         if (!tmp_ctx) {
8676                 return WERR_NOMEM;
8677         }
8678
8679         status = winreg_printer_binding_handle(tmp_ctx,
8680                                                get_session_info_system(),
8681                                                p->msg_ctx,
8682                                                &b);
8683         if (!W_ERROR_IS_OK(status)) {
8684                 goto done;
8685         }
8686
8687         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8688         if (!W_ERROR_IS_OK(status)) {
8689                 goto done;
8690         }
8691
8692         /*
8693          * ChangeID must always be set if this is a printer
8694          */
8695         if (Printer->printer_type == SPLHND_PRINTER) {
8696                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8697                         status = WERR_BADFID;
8698                         goto done;
8699                 }
8700
8701                 status = winreg_printer_update_changeid(tmp_ctx, b,
8702                                                         lp_const_servicename(snum));
8703         }
8704
8705 done:
8706         talloc_free(tmp_ctx);
8707         return status;
8708 }
8709
8710 /****************************************************************
8711  _spoolss_SetForm
8712 ****************************************************************/
8713
8714 WERROR _spoolss_SetForm(struct pipes_struct *p,
8715                         struct spoolss_SetForm *r)
8716 {
8717         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8718         const char *form_name = r->in.form_name;
8719         int snum = -1;
8720         WERROR status = WERR_OK;
8721         struct dcerpc_binding_handle *b;
8722         TALLOC_CTX *tmp_ctx = NULL;
8723
8724         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8725
8726         DEBUG(5,("_spoolss_SetForm\n"));
8727
8728         if (!Printer) {
8729                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8730                         OUR_HANDLE(r->in.handle)));
8731                 return WERR_BADFID;
8732         }
8733
8734         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8735            and not a printer admin, then fail */
8736
8737         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8738              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8739              !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8740                                           p->session_info->info->domain_name,
8741                                           NULL,
8742                                           p->session_info->security_token,
8743                                           lp_printer_admin(snum))) {
8744                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8745                 return WERR_ACCESS_DENIED;
8746         }
8747
8748         tmp_ctx = talloc_new(p->mem_ctx);
8749         if (!tmp_ctx) {
8750                 return WERR_NOMEM;
8751         }
8752
8753         status = winreg_printer_binding_handle(tmp_ctx,
8754                                                get_session_info_system(),
8755                                                p->msg_ctx,
8756                                                &b);
8757         if (!W_ERROR_IS_OK(status)) {
8758                 goto done;
8759         }
8760
8761         status = winreg_printer_setform1(tmp_ctx, b,
8762                                          form_name,
8763                                          form);
8764         if (!W_ERROR_IS_OK(status)) {
8765                 goto done;
8766         }
8767
8768         /*
8769          * ChangeID must always be set if this is a printer
8770          */
8771         if (Printer->printer_type == SPLHND_PRINTER) {
8772                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8773                         status = WERR_BADFID;
8774                         goto done;
8775                 }
8776
8777                 status = winreg_printer_update_changeid(tmp_ctx, b,
8778                                                         lp_const_servicename(snum));
8779         }
8780
8781 done:
8782         talloc_free(tmp_ctx);
8783         return status;
8784 }
8785
8786 /****************************************************************************
8787  fill_print_processor1
8788 ****************************************************************************/
8789
8790 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8791                                     struct spoolss_PrintProcessorInfo1 *r,
8792                                     const char *print_processor_name)
8793 {
8794         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8795         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8796
8797         return WERR_OK;
8798 }
8799
8800 /****************************************************************************
8801  enumprintprocessors level 1.
8802 ****************************************************************************/
8803
8804 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8805                                           union spoolss_PrintProcessorInfo **info_p,
8806                                           uint32_t *count)
8807 {
8808         union spoolss_PrintProcessorInfo *info;
8809         WERROR result;
8810
8811         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8812         W_ERROR_HAVE_NO_MEMORY(info);
8813
8814         *count = 1;
8815
8816         result = fill_print_processor1(info, &info[0].info1, "winprint");
8817         if (!W_ERROR_IS_OK(result)) {
8818                 goto out;
8819         }
8820
8821  out:
8822         if (!W_ERROR_IS_OK(result)) {
8823                 TALLOC_FREE(info);
8824                 *count = 0;
8825                 return result;
8826         }
8827
8828         *info_p = info;
8829
8830         return WERR_OK;
8831 }
8832
8833 /****************************************************************
8834  _spoolss_EnumPrintProcessors
8835 ****************************************************************/
8836
8837 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8838                                     struct spoolss_EnumPrintProcessors *r)
8839 {
8840         WERROR result;
8841
8842         /* that's an [in out] buffer */
8843
8844         if (!r->in.buffer && (r->in.offered != 0)) {
8845                 return WERR_INVALID_PARAM;
8846         }
8847
8848         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8849
8850         /*
8851          * Enumerate the print processors ...
8852          *
8853          * Just reply with "winprint", to keep NT happy
8854          * and I can use my nice printer checker.
8855          */
8856
8857         *r->out.count = 0;
8858         *r->out.needed = 0;
8859         *r->out.info = NULL;
8860
8861         if (!get_short_archi(r->in.environment)) {
8862                 return WERR_INVALID_ENVIRONMENT;
8863         }
8864
8865         switch (r->in.level) {
8866         case 1:
8867                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8868                                                      r->out.count);
8869                 break;
8870         default:
8871                 return WERR_UNKNOWN_LEVEL;
8872         }
8873
8874         if (!W_ERROR_IS_OK(result)) {
8875                 return result;
8876         }
8877
8878         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8879                                                      spoolss_EnumPrintProcessors,
8880                                                      *r->out.info, r->in.level,
8881                                                      *r->out.count);
8882         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8883         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8884
8885         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8886 }
8887
8888 /****************************************************************************
8889  fill_printprocdatatype1
8890 ****************************************************************************/
8891
8892 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8893                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8894                                       const char *name_array)
8895 {
8896         r->name_array = talloc_strdup(mem_ctx, name_array);
8897         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8898
8899         return WERR_OK;
8900 }
8901
8902 /****************************************************************************
8903  enumprintprocdatatypes level 1.
8904 ****************************************************************************/
8905
8906 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8907                                              union spoolss_PrintProcDataTypesInfo **info_p,
8908                                              uint32_t *count)
8909 {
8910         WERROR result;
8911         union spoolss_PrintProcDataTypesInfo *info;
8912
8913         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8914         W_ERROR_HAVE_NO_MEMORY(info);
8915
8916         *count = 1;
8917
8918         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8919         if (!W_ERROR_IS_OK(result)) {
8920                 goto out;
8921         }
8922
8923  out:
8924         if (!W_ERROR_IS_OK(result)) {
8925                 TALLOC_FREE(info);
8926                 *count = 0;
8927                 return result;
8928         }
8929
8930         *info_p = info;
8931
8932         return WERR_OK;
8933 }
8934
8935 /****************************************************************
8936  _spoolss_EnumPrintProcDataTypes
8937 ****************************************************************/
8938
8939 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8940                                        struct spoolss_EnumPrintProcDataTypes *r)
8941 {
8942         WERROR result;
8943
8944         /* that's an [in out] buffer */
8945
8946         if (!r->in.buffer && (r->in.offered != 0)) {
8947                 return WERR_INVALID_PARAM;
8948         }
8949
8950         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8951
8952         *r->out.count = 0;
8953         *r->out.needed = 0;
8954         *r->out.info = NULL;
8955
8956         if (r->in.print_processor_name == NULL ||
8957             !strequal(r->in.print_processor_name, "winprint")) {
8958                 return WERR_UNKNOWN_PRINTPROCESSOR;
8959         }
8960
8961         switch (r->in.level) {
8962         case 1:
8963                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8964                                                         r->out.count);
8965                 break;
8966         default:
8967                 return WERR_UNKNOWN_LEVEL;
8968         }
8969
8970         if (!W_ERROR_IS_OK(result)) {
8971                 return result;
8972         }
8973
8974         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8975                                                      spoolss_EnumPrintProcDataTypes,
8976                                                      *r->out.info, r->in.level,
8977                                                      *r->out.count);
8978         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8979         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8980
8981         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8982 }
8983
8984 /****************************************************************************
8985  fill_monitor_1
8986 ****************************************************************************/
8987
8988 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8989                              struct spoolss_MonitorInfo1 *r,
8990                              const char *monitor_name)
8991 {
8992         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
8993         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8994
8995         return WERR_OK;
8996 }
8997
8998 /****************************************************************************
8999  fill_monitor_2
9000 ****************************************************************************/
9001
9002 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9003                              struct spoolss_MonitorInfo2 *r,
9004                              const char *monitor_name,
9005                              const char *environment,
9006                              const char *dll_name)
9007 {
9008         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9009         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9010         r->environment                  = talloc_strdup(mem_ctx, environment);
9011         W_ERROR_HAVE_NO_MEMORY(r->environment);
9012         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9013         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9014
9015         return WERR_OK;
9016 }
9017
9018 /****************************************************************************
9019  enumprintmonitors level 1.
9020 ****************************************************************************/
9021
9022 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9023                                         union spoolss_MonitorInfo **info_p,
9024                                         uint32_t *count)
9025 {
9026         union spoolss_MonitorInfo *info;
9027         WERROR result = WERR_OK;
9028
9029         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9030         W_ERROR_HAVE_NO_MEMORY(info);
9031
9032         *count = 2;
9033
9034         result = fill_monitor_1(info, &info[0].info1,
9035                                 SPL_LOCAL_PORT);
9036         if (!W_ERROR_IS_OK(result)) {
9037                 goto out;
9038         }
9039
9040         result = fill_monitor_1(info, &info[1].info1,
9041                                 SPL_TCPIP_PORT);
9042         if (!W_ERROR_IS_OK(result)) {
9043                 goto out;
9044         }
9045
9046 out:
9047         if (!W_ERROR_IS_OK(result)) {
9048                 TALLOC_FREE(info);
9049                 *count = 0;
9050                 return result;
9051         }
9052
9053         *info_p = info;
9054
9055         return WERR_OK;
9056 }
9057
9058 /****************************************************************************
9059  enumprintmonitors level 2.
9060 ****************************************************************************/
9061
9062 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9063                                         union spoolss_MonitorInfo **info_p,
9064                                         uint32_t *count)
9065 {
9066         union spoolss_MonitorInfo *info;
9067         WERROR result = WERR_OK;
9068
9069         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9070         W_ERROR_HAVE_NO_MEMORY(info);
9071
9072         *count = 2;
9073
9074         result = fill_monitor_2(info, &info[0].info2,
9075                                 SPL_LOCAL_PORT,
9076                                 "Windows NT X86", /* FIXME */
9077                                 "localmon.dll");
9078         if (!W_ERROR_IS_OK(result)) {
9079                 goto out;
9080         }
9081
9082         result = fill_monitor_2(info, &info[1].info2,
9083                                 SPL_TCPIP_PORT,
9084                                 "Windows NT X86", /* FIXME */
9085                                 "tcpmon.dll");
9086         if (!W_ERROR_IS_OK(result)) {
9087                 goto out;
9088         }
9089
9090 out:
9091         if (!W_ERROR_IS_OK(result)) {
9092                 TALLOC_FREE(info);
9093                 *count = 0;
9094                 return result;
9095         }
9096
9097         *info_p = info;
9098
9099         return WERR_OK;
9100 }
9101
9102 /****************************************************************
9103  _spoolss_EnumMonitors
9104 ****************************************************************/
9105
9106 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9107                              struct spoolss_EnumMonitors *r)
9108 {
9109         WERROR result;
9110
9111         /* that's an [in out] buffer */
9112
9113         if (!r->in.buffer && (r->in.offered != 0)) {
9114                 return WERR_INVALID_PARAM;
9115         }
9116
9117         DEBUG(5,("_spoolss_EnumMonitors\n"));
9118
9119         /*
9120          * Enumerate the print monitors ...
9121          *
9122          * Just reply with "Local Port", to keep NT happy
9123          * and I can use my nice printer checker.
9124          */
9125
9126         *r->out.count = 0;
9127         *r->out.needed = 0;
9128         *r->out.info = NULL;
9129
9130         switch (r->in.level) {
9131         case 1:
9132                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9133                                                    r->out.count);
9134                 break;
9135         case 2:
9136                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9137                                                    r->out.count);
9138                 break;
9139         default:
9140                 return WERR_UNKNOWN_LEVEL;
9141         }
9142
9143         if (!W_ERROR_IS_OK(result)) {
9144                 return result;
9145         }
9146
9147         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9148                                                      spoolss_EnumMonitors,
9149                                                      *r->out.info, r->in.level,
9150                                                      *r->out.count);
9151         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9152         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9153
9154         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9155 }
9156
9157 /****************************************************************************
9158 ****************************************************************************/
9159
9160 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9161                              const print_queue_struct *queue,
9162                              int count, int snum,
9163                              struct spoolss_PrinterInfo2 *pinfo2,
9164                              uint32_t jobid,
9165                              struct spoolss_JobInfo1 *r)
9166 {
9167         int i = 0;
9168         bool found = false;
9169
9170         for (i=0; i<count; i++) {
9171                 if (queue[i].job == (int)jobid) {
9172                         found = true;
9173                         break;
9174                 }
9175         }
9176
9177         if (found == false) {
9178                 /* NT treats not found as bad param... yet another bad choice */
9179                 return WERR_INVALID_PARAM;
9180         }
9181
9182         return fill_job_info1(mem_ctx,
9183                               r,
9184                               &queue[i],
9185                               i,
9186                               snum,
9187                               pinfo2);
9188 }
9189
9190 /****************************************************************************
9191 ****************************************************************************/
9192
9193 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9194                              const print_queue_struct *queue,
9195                              int count, int snum,
9196                              struct spoolss_PrinterInfo2 *pinfo2,
9197                              uint32_t jobid,
9198                              struct spoolss_JobInfo2 *r)
9199 {
9200         int i = 0;
9201         bool found = false;
9202         struct spoolss_DeviceMode *devmode;
9203         WERROR result;
9204
9205         for (i=0; i<count; i++) {
9206                 if (queue[i].job == (int)jobid) {
9207                         found = true;
9208                         break;
9209                 }
9210         }
9211
9212         if (found == false) {
9213                 /* NT treats not found as bad param... yet another bad
9214                    choice */
9215                 return WERR_INVALID_PARAM;
9216         }
9217
9218         /*
9219          * if the print job does not have a DEVMODE associated with it,
9220          * just use the one for the printer. A NULL devicemode is not
9221          *  a failure condition
9222          */
9223
9224         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9225         if (!devmode) {
9226                 result = spoolss_create_default_devmode(mem_ctx,
9227                                                 pinfo2->printername,
9228                                                 &devmode);
9229                 if (!W_ERROR_IS_OK(result)) {
9230                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9231                         return result;
9232                 }
9233         }
9234
9235         return fill_job_info2(mem_ctx,
9236                               r,
9237                               &queue[i],
9238                               i,
9239                               snum,
9240                               pinfo2,
9241                               devmode);
9242 }
9243
9244 /****************************************************************
9245  _spoolss_GetJob
9246 ****************************************************************/
9247
9248 WERROR _spoolss_GetJob(struct pipes_struct *p,
9249                        struct spoolss_GetJob *r)
9250 {
9251         WERROR result = WERR_OK;
9252         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9253         int snum;
9254         int count;
9255         print_queue_struct      *queue = NULL;
9256         print_status_struct prt_status;
9257
9258         /* that's an [in out] buffer */
9259
9260         if (!r->in.buffer && (r->in.offered != 0)) {
9261                 return WERR_INVALID_PARAM;
9262         }
9263
9264         DEBUG(5,("_spoolss_GetJob\n"));
9265
9266         *r->out.needed = 0;
9267
9268         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9269                 return WERR_BADFID;
9270         }
9271
9272         result = winreg_get_printer_internal(p->mem_ctx,
9273                                     get_session_info_system(),
9274                                     p->msg_ctx,
9275                                     lp_const_servicename(snum),
9276                                     &pinfo2);
9277         if (!W_ERROR_IS_OK(result)) {
9278                 return result;
9279         }
9280
9281         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9282
9283         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9284                      count, prt_status.status, prt_status.message));
9285
9286         switch (r->in.level) {
9287         case 1:
9288                 result = getjob_level_1(p->mem_ctx,
9289                                         queue, count, snum, pinfo2,
9290                                         r->in.job_id, &r->out.info->info1);
9291                 break;
9292         case 2:
9293                 result = getjob_level_2(p->mem_ctx,
9294                                         queue, count, snum, pinfo2,
9295                                         r->in.job_id, &r->out.info->info2);
9296                 break;
9297         default:
9298                 result = WERR_UNKNOWN_LEVEL;
9299                 break;
9300         }
9301
9302         SAFE_FREE(queue);
9303         TALLOC_FREE(pinfo2);
9304
9305         if (!W_ERROR_IS_OK(result)) {
9306                 TALLOC_FREE(r->out.info);
9307                 return result;
9308         }
9309
9310         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9311                                                                                    r->in.level);
9312         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9313
9314         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9315 }
9316
9317 /****************************************************************
9318  _spoolss_GetPrinterDataEx
9319 ****************************************************************/
9320
9321 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9322                                  struct spoolss_GetPrinterDataEx *r)
9323 {
9324
9325         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9326         const char *printer;
9327         int                     snum = 0;
9328         WERROR result = WERR_OK;
9329         DATA_BLOB blob;
9330         enum winreg_Type val_type = REG_NONE;
9331         uint8_t *val_data = NULL;
9332         uint32_t val_size = 0;
9333         struct dcerpc_binding_handle *b;
9334         TALLOC_CTX *tmp_ctx;
9335
9336         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9337
9338         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9339                 r->in.key_name, r->in.value_name));
9340
9341         /* in case of problem, return some default values */
9342
9343         *r->out.needed  = 0;
9344         *r->out.type    = REG_NONE;
9345
9346         tmp_ctx = talloc_new(p->mem_ctx);
9347         if (!tmp_ctx) {
9348                 return WERR_NOMEM;
9349         }
9350
9351         if (!Printer) {
9352                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9353                         OUR_HANDLE(r->in.handle)));
9354                 result = WERR_BADFID;
9355                 goto done;
9356         }
9357
9358         /* check to see if the keyname is valid */
9359         if (!strlen(r->in.key_name)) {
9360                 result = WERR_INVALID_PARAM;
9361                 goto done;
9362         }
9363
9364         /* Is the handle to a printer or to the server? */
9365
9366         if (Printer->printer_type == SPLHND_SERVER) {
9367
9368                 union spoolss_PrinterData data;
9369
9370                 result = getprinterdata_printer_server(tmp_ctx,
9371                                                        r->in.value_name,
9372                                                        r->out.type,
9373                                                        &data);
9374                 if (!W_ERROR_IS_OK(result)) {
9375                         goto done;
9376                 }
9377
9378                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9379                                                   *r->out.type, &data);
9380                 if (!W_ERROR_IS_OK(result)) {
9381                         goto done;
9382                 }
9383
9384                 *r->out.needed = blob.length;
9385
9386                 if (r->in.offered >= *r->out.needed) {
9387                         memcpy(r->out.data, blob.data, blob.length);
9388                 }
9389
9390                 result = WERR_OK;
9391                 goto done;
9392         }
9393
9394         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9395                 result = WERR_BADFID;
9396                 goto done;
9397         }
9398         printer = lp_const_servicename(snum);
9399
9400         result = winreg_printer_binding_handle(tmp_ctx,
9401                                                get_session_info_system(),
9402                                                p->msg_ctx,
9403                                                &b);
9404         if (!W_ERROR_IS_OK(result)) {
9405                 goto done;
9406         }
9407
9408         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9409         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9410             strequal(r->in.value_name, "ChangeId")) {
9411                 *r->out.type = REG_DWORD;
9412                 *r->out.needed = 4;
9413                 if (r->in.offered >= *r->out.needed) {
9414                         uint32_t changeid = 0;
9415
9416                         result = winreg_printer_get_changeid(tmp_ctx, b,
9417                                                              printer,
9418                                                              &changeid);
9419                         if (!W_ERROR_IS_OK(result)) {
9420                                 goto done;
9421                         }
9422
9423                         SIVAL(r->out.data, 0, changeid);
9424                         result = WERR_OK;
9425                 }
9426                 goto done;
9427         }
9428
9429         result = winreg_get_printer_dataex(tmp_ctx, b,
9430                                            printer,
9431                                            r->in.key_name,
9432                                            r->in.value_name,
9433                                            &val_type,
9434                                            &val_data,
9435                                            &val_size);
9436         if (!W_ERROR_IS_OK(result)) {
9437                 goto done;
9438         }
9439
9440         *r->out.needed = val_size;
9441         *r->out.type = val_type;
9442
9443         if (r->in.offered >= *r->out.needed) {
9444                 memcpy(r->out.data, val_data, val_size);
9445         }
9446
9447 done:
9448         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9449
9450         if (W_ERROR_IS_OK(result)) {
9451                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9452         }
9453
9454         talloc_free(tmp_ctx);
9455         return result;
9456 }
9457
9458 /****************************************************************
9459  _spoolss_SetPrinterDataEx
9460 ****************************************************************/
9461
9462 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9463                                  struct spoolss_SetPrinterDataEx *r)
9464 {
9465         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9466         int                     snum = 0;
9467         WERROR                  result = WERR_OK;
9468         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9469         char                    *oid_string;
9470         struct dcerpc_binding_handle *b;
9471         TALLOC_CTX *tmp_ctx;
9472
9473         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9474
9475         /* From MSDN documentation of SetPrinterDataEx: pass request to
9476            SetPrinterData if key is "PrinterDriverData" */
9477
9478         if (!Printer) {
9479                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9480                         OUR_HANDLE(r->in.handle)));
9481                 return WERR_BADFID;
9482         }
9483
9484         if (Printer->printer_type == SPLHND_SERVER) {
9485                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9486                         "Not implemented for server handles yet\n"));
9487                 return WERR_INVALID_PARAM;
9488         }
9489
9490         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9491                 return WERR_BADFID;
9492         }
9493
9494         /*
9495          * Access check : NT returns "access denied" if you make a
9496          * SetPrinterData call without the necessary privildge.
9497          * we were originally returning OK if nothing changed
9498          * which made Win2k issue **a lot** of SetPrinterData
9499          * when connecting to a printer  --jerry
9500          */
9501
9502         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9503                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9504                         "change denied by handle access permissions\n"));
9505                 return WERR_ACCESS_DENIED;
9506         }
9507
9508         tmp_ctx = talloc_new(p->mem_ctx);
9509         if (!tmp_ctx) {
9510                 return WERR_NOMEM;
9511         }
9512
9513         result = winreg_printer_binding_handle(tmp_ctx,
9514                                                get_session_info_system(),
9515                                                p->msg_ctx,
9516                                                &b);
9517         if (!W_ERROR_IS_OK(result)) {
9518                 goto done;
9519         }
9520
9521         result = winreg_get_printer(tmp_ctx, b,
9522                                     lp_servicename(snum),
9523                                     &pinfo2);
9524         if (!W_ERROR_IS_OK(result)) {
9525                 goto done;
9526         }
9527
9528         /* check for OID in valuename */
9529
9530         oid_string = strchr(r->in.value_name, ',');
9531         if (oid_string) {
9532                 *oid_string = '\0';
9533                 oid_string++;
9534         }
9535
9536         /* save the registry data */
9537
9538         result = winreg_set_printer_dataex(tmp_ctx, b,
9539                                            pinfo2->sharename,
9540                                            r->in.key_name,
9541                                            r->in.value_name,
9542                                            r->in.type,
9543                                            r->in.data,
9544                                            r->in.offered);
9545
9546         if (W_ERROR_IS_OK(result)) {
9547                 /* save the OID if one was specified */
9548                 if (oid_string) {
9549                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9550                                 r->in.key_name, SPOOL_OID_KEY);
9551                         if (!str) {
9552                                 result = WERR_NOMEM;
9553                                 goto done;
9554                         }
9555
9556                         /*
9557                          * I'm not checking the status here on purpose.  Don't know
9558                          * if this is right, but I'm returning the status from the
9559                          * previous set_printer_dataex() call.  I have no idea if
9560                          * this is right.    --jerry
9561                          */
9562                         winreg_set_printer_dataex(tmp_ctx, b,
9563                                                   pinfo2->sharename,
9564                                                   str,
9565                                                   r->in.value_name,
9566                                                   REG_SZ,
9567                                                   (uint8_t *) oid_string,
9568                                                   strlen(oid_string) + 1);
9569                 }
9570
9571                 result = winreg_printer_update_changeid(tmp_ctx, b,
9572                                                         lp_const_servicename(snum));
9573
9574         }
9575
9576 done:
9577         talloc_free(tmp_ctx);
9578         return result;
9579 }
9580
9581 /****************************************************************
9582  _spoolss_DeletePrinterDataEx
9583 ****************************************************************/
9584
9585 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9586                                     struct spoolss_DeletePrinterDataEx *r)
9587 {
9588         const char *printer;
9589         int             snum=0;
9590         WERROR          status = WERR_OK;
9591         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9592
9593         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9594
9595         if (!Printer) {
9596                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9597                         "Invalid handle (%s:%u:%u).\n",
9598                         OUR_HANDLE(r->in.handle)));
9599                 return WERR_BADFID;
9600         }
9601
9602         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9603                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9604                         "printer properties change denied by handle\n"));
9605                 return WERR_ACCESS_DENIED;
9606         }
9607
9608         if (!r->in.value_name || !r->in.key_name) {
9609                 return WERR_NOMEM;
9610         }
9611
9612         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9613                 return WERR_BADFID;
9614         }
9615         printer = lp_const_servicename(snum);
9616
9617         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9618                                               get_session_info_system(),
9619                                               p->msg_ctx,
9620                                               printer,
9621                                               r->in.key_name,
9622                                               r->in.value_name);
9623         if (W_ERROR_IS_OK(status)) {
9624                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9625                                                         get_session_info_system(),
9626                                                         p->msg_ctx,
9627                                                         printer);
9628         }
9629
9630         return status;
9631 }
9632
9633 /****************************************************************
9634  _spoolss_EnumPrinterKey
9635 ****************************************************************/
9636
9637 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9638                                struct spoolss_EnumPrinterKey *r)
9639 {
9640         uint32_t        num_keys;
9641         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9642         int             snum = 0;
9643         WERROR          result = WERR_BADFILE;
9644         const char **array = NULL;
9645         DATA_BLOB blob;
9646
9647         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9648
9649         if (!Printer) {
9650                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9651                         OUR_HANDLE(r->in.handle)));
9652                 return WERR_BADFID;
9653         }
9654
9655         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9656                 return WERR_BADFID;
9657         }
9658
9659         result = winreg_enum_printer_key_internal(p->mem_ctx,
9660                                          get_session_info_system(),
9661                                          p->msg_ctx,
9662                                          lp_const_servicename(snum),
9663                                          r->in.key_name,
9664                                          &num_keys,
9665                                          &array);
9666         if (!W_ERROR_IS_OK(result)) {
9667                 goto done;
9668         }
9669
9670         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9671                 result = WERR_NOMEM;
9672                 goto done;
9673         }
9674
9675         *r->out._ndr_size = r->in.offered / 2;
9676         *r->out.needed = blob.length;
9677
9678         if (r->in.offered < *r->out.needed) {
9679                 result = WERR_MORE_DATA;
9680         } else {
9681                 result = WERR_OK;
9682                 r->out.key_buffer->string_array = array;
9683         }
9684
9685  done:
9686         if (!W_ERROR_IS_OK(result)) {
9687                 TALLOC_FREE(array);
9688                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9689                         *r->out.needed = 0;
9690                 }
9691         }
9692
9693         return result;
9694 }
9695
9696 /****************************************************************
9697  _spoolss_DeletePrinterKey
9698 ****************************************************************/
9699
9700 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9701                                  struct spoolss_DeletePrinterKey *r)
9702 {
9703         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9704         int                     snum=0;
9705         WERROR                  status;
9706         const char *printer;
9707         struct dcerpc_binding_handle *b;
9708         TALLOC_CTX *tmp_ctx;
9709
9710         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9711
9712         if (!Printer) {
9713                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9714                         OUR_HANDLE(r->in.handle)));
9715                 return WERR_BADFID;
9716         }
9717
9718         /* if keyname == NULL, return error */
9719         if ( !r->in.key_name )
9720                 return WERR_INVALID_PARAM;
9721
9722         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9723                 return WERR_BADFID;
9724         }
9725
9726         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9727                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9728                         "printer properties change denied by handle\n"));
9729                 return WERR_ACCESS_DENIED;
9730         }
9731
9732         printer = lp_const_servicename(snum);
9733
9734         tmp_ctx = talloc_new(p->mem_ctx);
9735         if (!tmp_ctx) {
9736                 return WERR_NOMEM;
9737         }
9738
9739         status = winreg_printer_binding_handle(tmp_ctx,
9740                                                get_session_info_system(),
9741                                                p->msg_ctx,
9742                                                &b);
9743         if (!W_ERROR_IS_OK(status)) {
9744                 goto done;
9745         }
9746
9747         /* delete the key and all subkeys */
9748         status = winreg_delete_printer_key(tmp_ctx, b,
9749                                            printer,
9750                                            r->in.key_name);
9751         if (W_ERROR_IS_OK(status)) {
9752                 status = winreg_printer_update_changeid(tmp_ctx, b,
9753                                                         printer);
9754         }
9755
9756 done:
9757         talloc_free(tmp_ctx);
9758         return status;
9759 }
9760
9761 /****************************************************************
9762  _spoolss_EnumPrinterDataEx
9763 ****************************************************************/
9764
9765 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9766                                   struct spoolss_EnumPrinterDataEx *r)
9767 {
9768         uint32_t        count = 0;
9769         struct spoolss_PrinterEnumValues *info = NULL;
9770         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9771         int             snum;
9772         WERROR          result;
9773
9774         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9775
9776         *r->out.count = 0;
9777         *r->out.needed = 0;
9778         *r->out.info = NULL;
9779
9780         if (!Printer) {
9781                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9782                         OUR_HANDLE(r->in.handle)));
9783                 return WERR_BADFID;
9784         }
9785
9786         /*
9787          * first check for a keyname of NULL or "".  Win2k seems to send
9788          * this a lot and we should send back WERR_INVALID_PARAM
9789          * no need to spend time looking up the printer in this case.
9790          * --jerry
9791          */
9792
9793         if (!strlen(r->in.key_name)) {
9794                 result = WERR_INVALID_PARAM;
9795                 goto done;
9796         }
9797
9798         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9799                 return WERR_BADFID;
9800         }
9801
9802         /* now look for a match on the key name */
9803         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9804                                             get_session_info_system(),
9805                                             p->msg_ctx,
9806                                             lp_const_servicename(snum),
9807                                             r->in.key_name,
9808                                             &count,
9809                                             &info);
9810         if (!W_ERROR_IS_OK(result)) {
9811                 goto done;
9812         }
9813
9814 #if 0 /* FIXME - gd */
9815         /* housekeeping information in the reply */
9816
9817         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9818          * the hand marshalled container size is a multiple
9819          * of 4 bytes for RPC alignment.
9820          */
9821
9822         if (needed % 4) {
9823                 needed += 4-(needed % 4);
9824         }
9825 #endif
9826         *r->out.count   = count;
9827         *r->out.info    = info;
9828
9829  done:
9830         if (!W_ERROR_IS_OK(result)) {
9831                 return result;
9832         }
9833
9834         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9835                                                spoolss_EnumPrinterDataEx,
9836                                                *r->out.info,
9837                                                *r->out.count);
9838         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9839         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9840
9841         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9842 }
9843
9844 /****************************************************************************
9845 ****************************************************************************/
9846
9847 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9848                                                  const char *servername,
9849                                                  const char *environment,
9850                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9851 {
9852         WERROR werr;
9853         char *path = NULL;
9854
9855         werr = compose_spoolss_server_path(mem_ctx,
9856                                            servername,
9857                                            environment,
9858                                            SPOOLSS_PRTPROCS_PATH,
9859                                            &path);
9860         if (!W_ERROR_IS_OK(werr)) {
9861                 return werr;
9862         }
9863
9864         DEBUG(4,("print processor directory: [%s]\n", path));
9865
9866         r->directory_name = path;
9867
9868         return WERR_OK;
9869 }
9870
9871 /****************************************************************
9872  _spoolss_GetPrintProcessorDirectory
9873 ****************************************************************/
9874
9875 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9876                                            struct spoolss_GetPrintProcessorDirectory *r)
9877 {
9878         WERROR result;
9879         char *prnproc_share = NULL;
9880         bool prnproc_share_exists = false;
9881         int snum;
9882
9883         /* that's an [in out] buffer */
9884
9885         if (!r->in.buffer && (r->in.offered != 0)) {
9886                 return WERR_INVALID_PARAM;
9887         }
9888
9889         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9890                 r->in.level));
9891
9892         *r->out.needed = 0;
9893
9894         /* r->in.level is ignored */
9895
9896         /* We always should reply with a local print processor directory so that
9897          * users are not forced to have a [prnproc$] share on the Samba spoolss
9898          * server, if users decide to do so, lets announce it though - Guenther */
9899
9900         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9901         if (!prnproc_share) {
9902                 return WERR_NOMEM;
9903         }
9904         if (snum != -1) {
9905                 prnproc_share_exists = true;
9906         }
9907
9908         result = getprintprocessordirectory_level_1(p->mem_ctx,
9909                                                     prnproc_share_exists ? r->in.server : NULL,
9910                                                     r->in.environment,
9911                                                     &r->out.info->info1);
9912         if (!W_ERROR_IS_OK(result)) {
9913                 TALLOC_FREE(r->out.info);
9914                 return result;
9915         }
9916
9917         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9918                                                                                    r->out.info, r->in.level);
9919         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9920
9921         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9922 }
9923
9924 /*******************************************************************
9925  ********************************************************************/
9926
9927 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9928                                const char *dllname)
9929 {
9930         enum ndr_err_code ndr_err;
9931         struct spoolss_MonitorUi ui;
9932
9933         ui.dll_name = dllname;
9934
9935         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9936                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9937         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9938                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9939         }
9940         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9941 }
9942
9943 /*******************************************************************
9944  Streams the monitor UI DLL name in UNICODE
9945 *******************************************************************/
9946
9947 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9948                                struct security_token *token, DATA_BLOB *in,
9949                                DATA_BLOB *out, uint32_t *needed)
9950 {
9951         const char *dllname = "tcpmonui.dll";
9952
9953         *needed = (strlen(dllname)+1) * 2;
9954
9955         if (out->length < *needed) {
9956                 return WERR_INSUFFICIENT_BUFFER;
9957         }
9958
9959         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9960                 return WERR_NOMEM;
9961         }
9962
9963         return WERR_OK;
9964 }
9965
9966 /*******************************************************************
9967  ********************************************************************/
9968
9969 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9970                              struct spoolss_PortData1 *port1,
9971                              const DATA_BLOB *buf)
9972 {
9973         enum ndr_err_code ndr_err;
9974         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9975                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9976         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9977                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9978         }
9979         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9980 }
9981
9982 /*******************************************************************
9983  ********************************************************************/
9984
9985 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9986                              struct spoolss_PortData2 *port2,
9987                              const DATA_BLOB *buf)
9988 {
9989         enum ndr_err_code ndr_err;
9990         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9991                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9992         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9993                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9994         }
9995         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9996 }
9997
9998 /*******************************************************************
9999  Create a new TCP/IP port
10000 *******************************************************************/
10001
10002 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10003                              struct security_token *token, DATA_BLOB *in,
10004                              DATA_BLOB *out, uint32_t *needed)
10005 {
10006         struct spoolss_PortData1 port1;
10007         struct spoolss_PortData2 port2;
10008         char *device_uri = NULL;
10009         uint32_t version;
10010
10011         const char *portname;
10012         const char *hostaddress;
10013         const char *queue;
10014         uint32_t port_number;
10015         uint32_t protocol;
10016
10017         /* peek for spoolss_PortData version */
10018
10019         if (!in || (in->length < (128 + 4))) {
10020                 return WERR_GENERAL_FAILURE;
10021         }
10022
10023         version = IVAL(in->data, 128);
10024
10025         switch (version) {
10026                 case 1:
10027                         ZERO_STRUCT(port1);
10028
10029                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10030                                 return WERR_NOMEM;
10031                         }
10032
10033                         portname        = port1.portname;
10034                         hostaddress     = port1.hostaddress;
10035                         queue           = port1.queue;
10036                         protocol        = port1.protocol;
10037                         port_number     = port1.port_number;
10038
10039                         break;
10040                 case 2:
10041                         ZERO_STRUCT(port2);
10042
10043                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10044                                 return WERR_NOMEM;
10045                         }
10046
10047                         portname        = port2.portname;
10048                         hostaddress     = port2.hostaddress;
10049                         queue           = port2.queue;
10050                         protocol        = port2.protocol;
10051                         port_number     = port2.port_number;
10052
10053                         break;
10054                 default:
10055                         DEBUG(1,("xcvtcp_addport: "
10056                                 "unknown version of port_data: %d\n", version));
10057                         return WERR_UNKNOWN_PORT;
10058         }
10059
10060         /* create the device URI and call the add_port_hook() */
10061
10062         switch (protocol) {
10063         case PROTOCOL_RAWTCP_TYPE:
10064                 device_uri = talloc_asprintf(mem_ctx,
10065                                 "socket://%s:%d/", hostaddress,
10066                                 port_number);
10067                 break;
10068
10069         case PROTOCOL_LPR_TYPE:
10070                 device_uri = talloc_asprintf(mem_ctx,
10071                         "lpr://%s/%s", hostaddress, queue );
10072                 break;
10073
10074         default:
10075                 return WERR_UNKNOWN_PORT;
10076         }
10077
10078         if (!device_uri) {
10079                 return WERR_NOMEM;
10080         }
10081
10082         return add_port_hook(mem_ctx, token, portname, device_uri);
10083 }
10084
10085 /*******************************************************************
10086 *******************************************************************/
10087
10088 struct xcv_api_table xcvtcp_cmds[] = {
10089         { "MonitorUI",  xcvtcp_monitorui },
10090         { "AddPort",    xcvtcp_addport},
10091         { NULL,         NULL }
10092 };
10093
10094 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10095                                      struct security_token *token, const char *command,
10096                                      DATA_BLOB *inbuf,
10097                                      DATA_BLOB *outbuf,
10098                                      uint32_t *needed )
10099 {
10100         int i;
10101
10102         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10103
10104         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10105                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10106                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10107         }
10108
10109         return WERR_BADFUNC;
10110 }
10111
10112 /*******************************************************************
10113 *******************************************************************/
10114 #if 0   /* don't support management using the "Local Port" monitor */
10115
10116 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10117                                  struct security_token *token, DATA_BLOB *in,
10118                                  DATA_BLOB *out, uint32_t *needed)
10119 {
10120         const char *dllname = "localui.dll";
10121
10122         *needed = (strlen(dllname)+1) * 2;
10123
10124         if (out->length < *needed) {
10125                 return WERR_INSUFFICIENT_BUFFER;
10126         }
10127
10128         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10129                 return WERR_NOMEM;
10130         }
10131
10132         return WERR_OK;
10133 }
10134
10135 /*******************************************************************
10136 *******************************************************************/
10137
10138 struct xcv_api_table xcvlocal_cmds[] = {
10139         { "MonitorUI",  xcvlocal_monitorui },
10140         { NULL,         NULL }
10141 };
10142 #else
10143 struct xcv_api_table xcvlocal_cmds[] = {
10144         { NULL,         NULL }
10145 };
10146 #endif
10147
10148
10149
10150 /*******************************************************************
10151 *******************************************************************/
10152
10153 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10154                                        struct security_token *token, const char *command,
10155                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10156                                        uint32_t *needed)
10157 {
10158         int i;
10159
10160         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10161
10162         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10163                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10164                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10165         }
10166         return WERR_BADFUNC;
10167 }
10168
10169 /****************************************************************
10170  _spoolss_XcvData
10171 ****************************************************************/
10172
10173 WERROR _spoolss_XcvData(struct pipes_struct *p,
10174                         struct spoolss_XcvData *r)
10175 {
10176         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10177         DATA_BLOB out_data = data_blob_null;
10178         WERROR werror;
10179
10180         if (!Printer) {
10181                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10182                         OUR_HANDLE(r->in.handle)));
10183                 return WERR_BADFID;
10184         }
10185
10186         /* Has to be a handle to the TCP/IP port monitor */
10187
10188         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10189                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10190                 return WERR_BADFID;
10191         }
10192
10193         /* requires administrative access to the server */
10194
10195         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10196                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10197                 return WERR_ACCESS_DENIED;
10198         }
10199
10200         /* Allocate the outgoing buffer */
10201
10202         if (r->in.out_data_size) {
10203                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10204                 if (out_data.data == NULL) {
10205                         return WERR_NOMEM;
10206                 }
10207         }
10208
10209         switch ( Printer->printer_type ) {
10210         case SPLHND_PORTMON_TCP:
10211                 werror = process_xcvtcp_command(p->mem_ctx,
10212                                                 p->session_info->security_token,
10213                                                 r->in.function_name,
10214                                                 &r->in.in_data, &out_data,
10215                                                 r->out.needed);
10216                 break;
10217         case SPLHND_PORTMON_LOCAL:
10218                 werror = process_xcvlocal_command(p->mem_ctx,
10219                                                   p->session_info->security_token,
10220                                                   r->in.function_name,
10221                                                   &r->in.in_data, &out_data,
10222                                                   r->out.needed);
10223                 break;
10224         default:
10225                 werror = WERR_INVALID_PRINT_MONITOR;
10226         }
10227
10228         if (!W_ERROR_IS_OK(werror)) {
10229                 return werror;
10230         }
10231
10232         *r->out.status_code = 0;
10233
10234         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10235                 memcpy(r->out.out_data, out_data.data,
10236                         MIN(r->in.out_data_size, out_data.length));
10237         }
10238
10239         return WERR_OK;
10240 }
10241
10242 /****************************************************************
10243  _spoolss_AddPrintProcessor
10244 ****************************************************************/
10245
10246 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10247                                   struct spoolss_AddPrintProcessor *r)
10248 {
10249         /* for now, just indicate success and ignore the add.  We'll
10250            automatically set the winprint processor for printer
10251            entries later.  Used to debug the LexMark Optra S 1855 PCL
10252            driver --jerry */
10253
10254         return WERR_OK;
10255 }
10256
10257 /****************************************************************
10258  _spoolss_AddPort
10259 ****************************************************************/
10260
10261 WERROR _spoolss_AddPort(struct pipes_struct *p,
10262                         struct spoolss_AddPort *r)
10263 {
10264         /* do what w2k3 does */
10265
10266         return WERR_NOT_SUPPORTED;
10267 }
10268
10269 /****************************************************************
10270  _spoolss_GetPrinterDriver
10271 ****************************************************************/
10272
10273 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10274                                  struct spoolss_GetPrinterDriver *r)
10275 {
10276         p->rng_fault_state = true;
10277         return WERR_NOT_SUPPORTED;
10278 }
10279
10280 /****************************************************************
10281  _spoolss_ReadPrinter
10282 ****************************************************************/
10283
10284 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10285                             struct spoolss_ReadPrinter *r)
10286 {
10287         p->rng_fault_state = true;
10288         return WERR_NOT_SUPPORTED;
10289 }
10290
10291 /****************************************************************
10292  _spoolss_WaitForPrinterChange
10293 ****************************************************************/
10294
10295 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10296                                      struct spoolss_WaitForPrinterChange *r)
10297 {
10298         p->rng_fault_state = true;
10299         return WERR_NOT_SUPPORTED;
10300 }
10301
10302 /****************************************************************
10303  _spoolss_ConfigurePort
10304 ****************************************************************/
10305
10306 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10307                               struct spoolss_ConfigurePort *r)
10308 {
10309         p->rng_fault_state = true;
10310         return WERR_NOT_SUPPORTED;
10311 }
10312
10313 /****************************************************************
10314  _spoolss_DeletePort
10315 ****************************************************************/
10316
10317 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10318                            struct spoolss_DeletePort *r)
10319 {
10320         p->rng_fault_state = true;
10321         return WERR_NOT_SUPPORTED;
10322 }
10323
10324 /****************************************************************
10325  _spoolss_CreatePrinterIC
10326 ****************************************************************/
10327
10328 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10329                                 struct spoolss_CreatePrinterIC *r)
10330 {
10331         p->rng_fault_state = true;
10332         return WERR_NOT_SUPPORTED;
10333 }
10334
10335 /****************************************************************
10336  _spoolss_PlayGDIScriptOnPrinterIC
10337 ****************************************************************/
10338
10339 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10340                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10341 {
10342         p->rng_fault_state = true;
10343         return WERR_NOT_SUPPORTED;
10344 }
10345
10346 /****************************************************************
10347  _spoolss_DeletePrinterIC
10348 ****************************************************************/
10349
10350 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10351                                 struct spoolss_DeletePrinterIC *r)
10352 {
10353         p->rng_fault_state = true;
10354         return WERR_NOT_SUPPORTED;
10355 }
10356
10357 /****************************************************************
10358  _spoolss_AddPrinterConnection
10359 ****************************************************************/
10360
10361 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10362                                      struct spoolss_AddPrinterConnection *r)
10363 {
10364         p->rng_fault_state = true;
10365         return WERR_NOT_SUPPORTED;
10366 }
10367
10368 /****************************************************************
10369  _spoolss_DeletePrinterConnection
10370 ****************************************************************/
10371
10372 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10373                                         struct spoolss_DeletePrinterConnection *r)
10374 {
10375         p->rng_fault_state = true;
10376         return WERR_NOT_SUPPORTED;
10377 }
10378
10379 /****************************************************************
10380  _spoolss_PrinterMessageBox
10381 ****************************************************************/
10382
10383 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10384                                   struct spoolss_PrinterMessageBox *r)
10385 {
10386         p->rng_fault_state = true;
10387         return WERR_NOT_SUPPORTED;
10388 }
10389
10390 /****************************************************************
10391  _spoolss_AddMonitor
10392 ****************************************************************/
10393
10394 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10395                            struct spoolss_AddMonitor *r)
10396 {
10397         p->rng_fault_state = true;
10398         return WERR_NOT_SUPPORTED;
10399 }
10400
10401 /****************************************************************
10402  _spoolss_DeleteMonitor
10403 ****************************************************************/
10404
10405 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10406                               struct spoolss_DeleteMonitor *r)
10407 {
10408         p->rng_fault_state = true;
10409         return WERR_NOT_SUPPORTED;
10410 }
10411
10412 /****************************************************************
10413  _spoolss_DeletePrintProcessor
10414 ****************************************************************/
10415
10416 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10417                                      struct spoolss_DeletePrintProcessor *r)
10418 {
10419         p->rng_fault_state = true;
10420         return WERR_NOT_SUPPORTED;
10421 }
10422
10423 /****************************************************************
10424  _spoolss_AddPrintProvidor
10425 ****************************************************************/
10426
10427 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10428                                  struct spoolss_AddPrintProvidor *r)
10429 {
10430         p->rng_fault_state = true;
10431         return WERR_NOT_SUPPORTED;
10432 }
10433
10434 /****************************************************************
10435  _spoolss_DeletePrintProvidor
10436 ****************************************************************/
10437
10438 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10439                                     struct spoolss_DeletePrintProvidor *r)
10440 {
10441         p->rng_fault_state = true;
10442         return WERR_NOT_SUPPORTED;
10443 }
10444
10445 /****************************************************************
10446  _spoolss_FindFirstPrinterChangeNotification
10447 ****************************************************************/
10448
10449 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10450                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10451 {
10452         p->rng_fault_state = true;
10453         return WERR_NOT_SUPPORTED;
10454 }
10455
10456 /****************************************************************
10457  _spoolss_FindNextPrinterChangeNotification
10458 ****************************************************************/
10459
10460 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10461                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10462 {
10463         p->rng_fault_state = true;
10464         return WERR_NOT_SUPPORTED;
10465 }
10466
10467 /****************************************************************
10468  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10469 ****************************************************************/
10470
10471 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10472                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10473 {
10474         p->rng_fault_state = true;
10475         return WERR_NOT_SUPPORTED;
10476 }
10477
10478 /****************************************************************
10479  _spoolss_ReplyOpenPrinter
10480 ****************************************************************/
10481
10482 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10483                                  struct spoolss_ReplyOpenPrinter *r)
10484 {
10485         p->rng_fault_state = true;
10486         return WERR_NOT_SUPPORTED;
10487 }
10488
10489 /****************************************************************
10490  _spoolss_RouterReplyPrinter
10491 ****************************************************************/
10492
10493 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10494                                    struct spoolss_RouterReplyPrinter *r)
10495 {
10496         p->rng_fault_state = true;
10497         return WERR_NOT_SUPPORTED;
10498 }
10499
10500 /****************************************************************
10501  _spoolss_ReplyClosePrinter
10502 ****************************************************************/
10503
10504 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10505                                   struct spoolss_ReplyClosePrinter *r)
10506 {
10507         p->rng_fault_state = true;
10508         return WERR_NOT_SUPPORTED;
10509 }
10510
10511 /****************************************************************
10512  _spoolss_AddPortEx
10513 ****************************************************************/
10514
10515 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10516                           struct spoolss_AddPortEx *r)
10517 {
10518         p->rng_fault_state = true;
10519         return WERR_NOT_SUPPORTED;
10520 }
10521
10522 /****************************************************************
10523  _spoolss_RouterFindFirstPrinterChangeNotification
10524 ****************************************************************/
10525
10526 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10527                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10528 {
10529         p->rng_fault_state = true;
10530         return WERR_NOT_SUPPORTED;
10531 }
10532
10533 /****************************************************************
10534  _spoolss_SpoolerInit
10535 ****************************************************************/
10536
10537 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10538                             struct spoolss_SpoolerInit *r)
10539 {
10540         p->rng_fault_state = true;
10541         return WERR_NOT_SUPPORTED;
10542 }
10543
10544 /****************************************************************
10545  _spoolss_ResetPrinterEx
10546 ****************************************************************/
10547
10548 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10549                                struct spoolss_ResetPrinterEx *r)
10550 {
10551         p->rng_fault_state = true;
10552         return WERR_NOT_SUPPORTED;
10553 }
10554
10555 /****************************************************************
10556  _spoolss_RouterReplyPrinterEx
10557 ****************************************************************/
10558
10559 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10560                                      struct spoolss_RouterReplyPrinterEx *r)
10561 {
10562         p->rng_fault_state = true;
10563         return WERR_NOT_SUPPORTED;
10564 }
10565
10566 /****************************************************************
10567  _spoolss_44
10568 ****************************************************************/
10569
10570 WERROR _spoolss_44(struct pipes_struct *p,
10571                    struct spoolss_44 *r)
10572 {
10573         p->rng_fault_state = true;
10574         return WERR_NOT_SUPPORTED;
10575 }
10576
10577 /****************************************************************
10578  _spoolss_SetPort
10579 ****************************************************************/
10580
10581 WERROR _spoolss_SetPort(struct pipes_struct *p,
10582                         struct spoolss_SetPort *r)
10583 {
10584         p->rng_fault_state = true;
10585         return WERR_NOT_SUPPORTED;
10586 }
10587
10588 /****************************************************************
10589  _spoolss_4a
10590 ****************************************************************/
10591
10592 WERROR _spoolss_4a(struct pipes_struct *p,
10593                    struct spoolss_4a *r)
10594 {
10595         p->rng_fault_state = true;
10596         return WERR_NOT_SUPPORTED;
10597 }
10598
10599 /****************************************************************
10600  _spoolss_4b
10601 ****************************************************************/
10602
10603 WERROR _spoolss_4b(struct pipes_struct *p,
10604                    struct spoolss_4b *r)
10605 {
10606         p->rng_fault_state = true;
10607         return WERR_NOT_SUPPORTED;
10608 }
10609
10610 /****************************************************************
10611  _spoolss_4c
10612 ****************************************************************/
10613
10614 WERROR _spoolss_4c(struct pipes_struct *p,
10615                    struct spoolss_4c *r)
10616 {
10617         p->rng_fault_state = true;
10618         return WERR_NOT_SUPPORTED;
10619 }
10620
10621 /****************************************************************
10622  _spoolss_53
10623 ****************************************************************/
10624
10625 WERROR _spoolss_53(struct pipes_struct *p,
10626                    struct spoolss_53 *r)
10627 {
10628         p->rng_fault_state = true;
10629         return WERR_NOT_SUPPORTED;
10630 }
10631
10632 /****************************************************************
10633  _spoolss_AddPerMachineConnection
10634 ****************************************************************/
10635
10636 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10637                                         struct spoolss_AddPerMachineConnection *r)
10638 {
10639         p->rng_fault_state = true;
10640         return WERR_NOT_SUPPORTED;
10641 }
10642
10643 /****************************************************************
10644  _spoolss_DeletePerMachineConnection
10645 ****************************************************************/
10646
10647 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10648                                            struct spoolss_DeletePerMachineConnection *r)
10649 {
10650         p->rng_fault_state = true;
10651         return WERR_NOT_SUPPORTED;
10652 }
10653
10654 /****************************************************************
10655  _spoolss_EnumPerMachineConnections
10656 ****************************************************************/
10657
10658 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10659                                           struct spoolss_EnumPerMachineConnections *r)
10660 {
10661         p->rng_fault_state = true;
10662         return WERR_NOT_SUPPORTED;
10663 }
10664
10665 /****************************************************************
10666  _spoolss_5a
10667 ****************************************************************/
10668
10669 WERROR _spoolss_5a(struct pipes_struct *p,
10670                    struct spoolss_5a *r)
10671 {
10672         p->rng_fault_state = true;
10673         return WERR_NOT_SUPPORTED;
10674 }
10675
10676 /****************************************************************
10677  _spoolss_5b
10678 ****************************************************************/
10679
10680 WERROR _spoolss_5b(struct pipes_struct *p,
10681                    struct spoolss_5b *r)
10682 {
10683         p->rng_fault_state = true;
10684         return WERR_NOT_SUPPORTED;
10685 }
10686
10687 /****************************************************************
10688  _spoolss_5c
10689 ****************************************************************/
10690
10691 WERROR _spoolss_5c(struct pipes_struct *p,
10692                    struct spoolss_5c *r)
10693 {
10694         p->rng_fault_state = true;
10695         return WERR_NOT_SUPPORTED;
10696 }
10697
10698 /****************************************************************
10699  _spoolss_5d
10700 ****************************************************************/
10701
10702 WERROR _spoolss_5d(struct pipes_struct *p,
10703                    struct spoolss_5d *r)
10704 {
10705         p->rng_fault_state = true;
10706         return WERR_NOT_SUPPORTED;
10707 }
10708
10709 /****************************************************************
10710  _spoolss_5e
10711 ****************************************************************/
10712
10713 WERROR _spoolss_5e(struct pipes_struct *p,
10714                    struct spoolss_5e *r)
10715 {
10716         p->rng_fault_state = true;
10717         return WERR_NOT_SUPPORTED;
10718 }
10719
10720 /****************************************************************
10721  _spoolss_5f
10722 ****************************************************************/
10723
10724 WERROR _spoolss_5f(struct pipes_struct *p,
10725                    struct spoolss_5f *r)
10726 {
10727         p->rng_fault_state = true;
10728         return WERR_NOT_SUPPORTED;
10729 }
10730
10731 /****************************************************************
10732  _spoolss_60
10733 ****************************************************************/
10734
10735 WERROR _spoolss_60(struct pipes_struct *p,
10736                    struct spoolss_60 *r)
10737 {
10738         p->rng_fault_state = true;
10739         return WERR_NOT_SUPPORTED;
10740 }
10741
10742 /****************************************************************
10743  _spoolss_61
10744 ****************************************************************/
10745
10746 WERROR _spoolss_61(struct pipes_struct *p,
10747                    struct spoolss_61 *r)
10748 {
10749         p->rng_fault_state = true;
10750         return WERR_NOT_SUPPORTED;
10751 }
10752
10753 /****************************************************************
10754  _spoolss_62
10755 ****************************************************************/
10756
10757 WERROR _spoolss_62(struct pipes_struct *p,
10758                    struct spoolss_62 *r)
10759 {
10760         p->rng_fault_state = true;
10761         return WERR_NOT_SUPPORTED;
10762 }
10763
10764 /****************************************************************
10765  _spoolss_63
10766 ****************************************************************/
10767
10768 WERROR _spoolss_63(struct pipes_struct *p,
10769                    struct spoolss_63 *r)
10770 {
10771         p->rng_fault_state = true;
10772         return WERR_NOT_SUPPORTED;
10773 }
10774
10775 /****************************************************************
10776  _spoolss_64
10777 ****************************************************************/
10778
10779 WERROR _spoolss_64(struct pipes_struct *p,
10780                    struct spoolss_64 *r)
10781 {
10782         p->rng_fault_state = true;
10783         return WERR_NOT_SUPPORTED;
10784 }
10785
10786 /****************************************************************
10787  _spoolss_65
10788 ****************************************************************/
10789
10790 WERROR _spoolss_65(struct pipes_struct *p,
10791                    struct spoolss_65 *r)
10792 {
10793         p->rng_fault_state = true;
10794         return WERR_NOT_SUPPORTED;
10795 }
10796
10797 /****************************************************************
10798  _spoolss_GetCorePrinterDrivers
10799 ****************************************************************/
10800
10801 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10802                                       struct spoolss_GetCorePrinterDrivers *r)
10803 {
10804         p->rng_fault_state = true;
10805         return WERR_NOT_SUPPORTED;
10806 }
10807
10808 /****************************************************************
10809  _spoolss_67
10810 ****************************************************************/
10811
10812 WERROR _spoolss_67(struct pipes_struct *p,
10813                    struct spoolss_67 *r)
10814 {
10815         p->rng_fault_state = true;
10816         return WERR_NOT_SUPPORTED;
10817 }
10818
10819 /****************************************************************
10820  _spoolss_GetPrinterDriverPackagePath
10821 ****************************************************************/
10822
10823 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10824                                             struct spoolss_GetPrinterDriverPackagePath *r)
10825 {
10826         p->rng_fault_state = true;
10827         return WERR_NOT_SUPPORTED;
10828 }
10829
10830 /****************************************************************
10831  _spoolss_69
10832 ****************************************************************/
10833
10834 WERROR _spoolss_69(struct pipes_struct *p,
10835                    struct spoolss_69 *r)
10836 {
10837         p->rng_fault_state = true;
10838         return WERR_NOT_SUPPORTED;
10839 }
10840
10841 /****************************************************************
10842  _spoolss_6a
10843 ****************************************************************/
10844
10845 WERROR _spoolss_6a(struct pipes_struct *p,
10846                    struct spoolss_6a *r)
10847 {
10848         p->rng_fault_state = true;
10849         return WERR_NOT_SUPPORTED;
10850 }
10851
10852 /****************************************************************
10853  _spoolss_6b
10854 ****************************************************************/
10855
10856 WERROR _spoolss_6b(struct pipes_struct *p,
10857                    struct spoolss_6b *r)
10858 {
10859         p->rng_fault_state = true;
10860         return WERR_NOT_SUPPORTED;
10861 }
10862
10863 /****************************************************************
10864  _spoolss_6c
10865 ****************************************************************/
10866
10867 WERROR _spoolss_6c(struct pipes_struct *p,
10868                    struct spoolss_6c *r)
10869 {
10870         p->rng_fault_state = true;
10871         return WERR_NOT_SUPPORTED;
10872 }
10873
10874 /****************************************************************
10875  _spoolss_6d
10876 ****************************************************************/
10877
10878 WERROR _spoolss_6d(struct pipes_struct *p,
10879                    struct spoolss_6d *r)
10880 {
10881         p->rng_fault_state = true;
10882         return WERR_NOT_SUPPORTED;
10883 }