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