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