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