loadparm: rename lp[cfg]_print_ok to lp[cfg]_printable for consistency with docs
[kai/samba-autobuild/.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         struct cli_state *cli;
142         uint32_t active_connections;
143 };
144
145 static struct notify_back_channel *back_channels;
146
147 /* Map generic permissions to printer object specific permissions */
148
149 const struct standard_mapping printer_std_mapping = {
150         PRINTER_READ,
151         PRINTER_WRITE,
152         PRINTER_EXECUTE,
153         PRINTER_ALL_ACCESS
154 };
155
156 /* Map generic permissions to print server object specific permissions */
157
158 const struct standard_mapping printserver_std_mapping = {
159         SERVER_READ,
160         SERVER_WRITE,
161         SERVER_EXECUTE,
162         SERVER_ALL_ACCESS
163 };
164
165 /* API table for Xcv Monitor functions */
166
167 struct xcv_api_table {
168         const char *name;
169         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
170 };
171
172 static void prune_printername_cache(void);
173
174 /********************************************************************
175  * Canonicalize servername.
176  ********************************************************************/
177
178 static const char *canon_servername(const char *servername)
179 {
180         const char *pservername = servername;
181         while (*pservername == '\\') {
182                 pservername++;
183         }
184         return pservername;
185 }
186
187 /* translate between internal status numbers and NT status numbers */
188 static int nt_printj_status(int v)
189 {
190         switch (v) {
191         case LPQ_QUEUED:
192                 return 0;
193         case LPQ_PAUSED:
194                 return JOB_STATUS_PAUSED;
195         case LPQ_SPOOLING:
196                 return JOB_STATUS_SPOOLING;
197         case LPQ_PRINTING:
198                 return JOB_STATUS_PRINTING;
199         case LPQ_ERROR:
200                 return JOB_STATUS_ERROR;
201         case LPQ_DELETING:
202                 return JOB_STATUS_DELETING;
203         case LPQ_OFFLINE:
204                 return JOB_STATUS_OFFLINE;
205         case LPQ_PAPEROUT:
206                 return JOB_STATUS_PAPEROUT;
207         case LPQ_PRINTED:
208                 return JOB_STATUS_PRINTED;
209         case LPQ_DELETED:
210                 return JOB_STATUS_DELETED;
211         case LPQ_BLOCKED:
212                 return JOB_STATUS_BLOCKED_DEVQ;
213         case LPQ_USER_INTERVENTION:
214                 return JOB_STATUS_USER_INTERVENTION;
215         }
216         return 0;
217 }
218
219 static int nt_printq_status(int v)
220 {
221         switch (v) {
222         case LPQ_PAUSED:
223                 return PRINTER_STATUS_PAUSED;
224         case LPQ_QUEUED:
225         case LPQ_SPOOLING:
226         case LPQ_PRINTING:
227                 return 0;
228         }
229         return 0;
230 }
231
232 /***************************************************************************
233  Disconnect from the client
234 ****************************************************************************/
235
236 static void srv_spoolss_replycloseprinter(int snum,
237                                           struct printer_handle *prn_hnd)
238 {
239         WERROR result;
240         NTSTATUS status;
241
242         /*
243          * Tell the specific printing tdb we no longer want messages for this printer
244          * by deregistering our PID.
245          */
246
247         if (!print_notify_deregister_pid(snum)) {
248                 DEBUG(0, ("Failed to register our pid for printer %s\n",
249                           lp_const_servicename(snum)));
250         }
251
252         /* weird if the test succeeds !!! */
253         if (prn_hnd->notify.cli_chan == NULL ||
254             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
255             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
256             prn_hnd->notify.cli_chan->active_connections == 0) {
257                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
258                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
259                 TALLOC_FREE(prn_hnd->notify.cli_chan);
260                 return;
261         }
262
263         status = dcerpc_spoolss_ReplyClosePrinter(
264                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
265                                         talloc_tos(),
266                                         &prn_hnd->notify.cli_hnd,
267                                         &result);
268         if (!NT_STATUS_IS_OK(status)) {
269                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
270                           nt_errstr(status)));
271                 result = ntstatus_to_werror(status);
272         } else if (!W_ERROR_IS_OK(result)) {
273                 DEBUG(0, ("reply_close_printer failed [%s].\n",
274                           win_errstr(result)));
275         }
276
277         /* if it's the last connection, deconnect the IPC$ share */
278         if (prn_hnd->notify.cli_chan->active_connections == 1) {
279
280                 cli_shutdown(prn_hnd->notify.cli_chan->cli);
281                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
282                 TALLOC_FREE(prn_hnd->notify.cli_chan);
283
284                 if (prn_hnd->notify.msg_ctx != NULL) {
285                         messaging_deregister(prn_hnd->notify.msg_ctx,
286                                              MSG_PRINTER_NOTIFY2, NULL);
287                 }
288         }
289
290         if (prn_hnd->notify.cli_chan) {
291                 prn_hnd->notify.cli_chan->active_connections--;
292                 prn_hnd->notify.cli_chan = NULL;
293         }
294 }
295
296 /****************************************************************************
297  Functions to free a printer entry datastruct.
298 ****************************************************************************/
299
300 static int printer_entry_destructor(struct printer_handle *Printer)
301 {
302         if (Printer->notify.cli_chan != NULL &&
303             Printer->notify.cli_chan->active_connections > 0) {
304                 int snum = -1;
305
306                 switch(Printer->printer_type) {
307                 case SPLHND_SERVER:
308                         srv_spoolss_replycloseprinter(snum, Printer);
309                         break;
310
311                 case SPLHND_PRINTER:
312                         snum = print_queue_snum(Printer->sharename);
313                         if (snum != -1) {
314                                 srv_spoolss_replycloseprinter(snum, Printer);
315                         }
316                         break;
317                 default:
318                         break;
319                 }
320         }
321
322         Printer->notify.flags=0;
323         Printer->notify.options=0;
324         Printer->notify.localmachine[0]='\0';
325         Printer->notify.printerlocal=0;
326         TALLOC_FREE(Printer->notify.option);
327         TALLOC_FREE(Printer->devmode);
328
329         /* Remove from the internal list. */
330         DLIST_REMOVE(printers_list, Printer);
331         return 0;
332 }
333
334 /****************************************************************************
335   find printer index by handle
336 ****************************************************************************/
337
338 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
339                                                         struct policy_handle *hnd)
340 {
341         struct printer_handle *find_printer = NULL;
342
343         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
344                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
345                 return NULL;
346         }
347
348         return find_printer;
349 }
350
351 /****************************************************************************
352  Close printer index by handle.
353 ****************************************************************************/
354
355 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
356 {
357         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
358
359         if (!Printer) {
360                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
361                         OUR_HANDLE(hnd)));
362                 return false;
363         }
364
365         close_policy_hnd(p, hnd);
366
367         return true;
368 }
369
370 /****************************************************************************
371  Delete a printer given a handle.
372 ****************************************************************************/
373
374 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
375                                   const char *sharename,
376                                   struct messaging_context *msg_ctx)
377 {
378         char *cmd = lp_deleteprinter_cmd(talloc_tos());
379         char *command = NULL;
380         int ret;
381         bool is_print_op = false;
382
383         /* can't fail if we don't try */
384
385         if ( !*cmd )
386                 return WERR_OK;
387
388         command = talloc_asprintf(ctx,
389                         "%s \"%s\"",
390                         cmd, sharename);
391         if (!command) {
392                 return WERR_NOMEM;
393         }
394         if ( token )
395                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
396
397         DEBUG(10,("Running [%s]\n", command));
398
399         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
400
401         if ( is_print_op )
402                 become_root();
403
404         if ( (ret = smbrun(command, NULL)) == 0 ) {
405                 /* Tell everyone we updated smb.conf. */
406                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
407         }
408
409         if ( is_print_op )
410                 unbecome_root();
411
412         /********** END SePrintOperatorPrivlege BLOCK **********/
413
414         DEBUGADD(10,("returned [%d]\n", ret));
415
416         TALLOC_FREE(command);
417
418         if (ret != 0)
419                 return WERR_BADFID; /* What to return here? */
420
421         return WERR_OK;
422 }
423
424 /****************************************************************************
425  Delete a printer given a handle.
426 ****************************************************************************/
427
428 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
429 {
430         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
431         WERROR result;
432
433         if (!Printer) {
434                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
435                         OUR_HANDLE(hnd)));
436                 return WERR_BADFID;
437         }
438
439         /*
440          * It turns out that Windows allows delete printer on a handle
441          * opened by an admin user, then used on a pipe handle created
442          * by an anonymous user..... but they're working on security.... riiight !
443          * JRA.
444          */
445
446         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
447                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
448                 return WERR_ACCESS_DENIED;
449         }
450
451         /* this does not need a become root since the access check has been
452            done on the handle already */
453
454         result = winreg_delete_printer_key_internal(p->mem_ctx,
455                                            get_session_info_system(),
456                                            p->msg_ctx,
457                                            Printer->sharename,
458                                            "");
459         if (!W_ERROR_IS_OK(result)) {
460                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
461                 return WERR_BADFID;
462         }
463
464         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
465                                      Printer->sharename, p->msg_ctx);
466         if (!W_ERROR_IS_OK(result)) {
467                 return result;
468         }
469         prune_printername_cache();
470         return WERR_OK;
471 }
472
473 /****************************************************************************
474  Return the snum of a printer corresponding to an handle.
475 ****************************************************************************/
476
477 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
478                              int *number, struct share_params **params)
479 {
480         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
481
482         if (!Printer) {
483                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
484                         OUR_HANDLE(hnd)));
485                 return false;
486         }
487
488         switch (Printer->printer_type) {
489                 case SPLHND_PRINTER:
490                         DEBUG(4,("short name:%s\n", Printer->sharename));
491                         *number = print_queue_snum(Printer->sharename);
492                         return (*number != -1);
493                 case SPLHND_SERVER:
494                         return false;
495                 default:
496                         return false;
497         }
498 }
499
500 /****************************************************************************
501  Set printer handle type.
502  Check if it's \\server or \\server\printer
503 ****************************************************************************/
504
505 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
506 {
507         DEBUG(3,("Setting printer type=%s\n", handlename));
508
509         /* it's a print server */
510         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
511                 DEBUGADD(4,("Printer is a print server\n"));
512                 Printer->printer_type = SPLHND_SERVER;
513         }
514         /* it's a printer (set_printer_hnd_name() will handle port monitors */
515         else {
516                 DEBUGADD(4,("Printer is a printer\n"));
517                 Printer->printer_type = SPLHND_PRINTER;
518         }
519
520         return true;
521 }
522
523 static void prune_printername_cache_fn(const char *key, const char *value,
524                                        time_t timeout, void *private_data)
525 {
526         gencache_del(key);
527 }
528
529 static void prune_printername_cache(void)
530 {
531         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
532 }
533
534 /****************************************************************************
535  Set printer handle name..  Accept names like \\server, \\server\printer,
536  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
537  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
538  XcvDataPort() interface.
539 ****************************************************************************/
540
541 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
542                                    const struct auth_session_info *session_info,
543                                    struct messaging_context *msg_ctx,
544                                    struct printer_handle *Printer,
545                                    const char *handlename)
546 {
547         int snum;
548         int n_services=lp_numservices();
549         char *aprinter;
550         const char *printername;
551         const char *servername = NULL;
552         fstring sname;
553         bool found = false;
554         struct spoolss_PrinterInfo2 *info2 = NULL;
555         WERROR result;
556         char *p;
557
558         /*
559          * Hopefully nobody names his printers like this. Maybe \ or ,
560          * are illegal in printer names even?
561          */
562         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
563         char *cache_key;
564         char *tmp;
565
566         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
567                 (unsigned long)strlen(handlename)));
568
569         aprinter = discard_const_p(char, handlename);
570         if ( *handlename == '\\' ) {
571                 servername = canon_servername(handlename);
572                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
573                         *aprinter = '\0';
574                         aprinter++;
575                 }
576                 if (!is_myname_or_ipaddr(servername)) {
577                         return WERR_INVALID_PRINTER_NAME;
578                 }
579                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
580                 if (Printer->servername == NULL) {
581                         return WERR_NOMEM;
582                 }
583         }
584
585         if (Printer->printer_type == SPLHND_SERVER) {
586                 return WERR_OK;
587         }
588
589         if (Printer->printer_type != SPLHND_PRINTER) {
590                 return WERR_INVALID_HANDLE;
591         }
592
593         DEBUGADD(5, ("searching for [%s]\n", aprinter));
594
595         p = strchr(aprinter, ',');
596         if (p != NULL) {
597                 char *p2 = p;
598                 p++;
599                 if (*p == ' ') {
600                         p++;
601                 }
602                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
603                         *p2 = '\0';
604                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
605                         *p2 = '\0';
606                 }
607         }
608
609         if (p) {
610                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
611         }
612
613         /* check for the Port Monitor Interface */
614         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
615                 Printer->printer_type = SPLHND_PORTMON_TCP;
616                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
617                 found = true;
618         }
619         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
620                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
621                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
622                 found = true;
623         }
624
625         /*
626          * With hundreds of printers, the "for" loop iterating all
627          * shares can be quite expensive, as it is done on every
628          * OpenPrinter. The loop maps "aprinter" to "sname", the
629          * result of which we cache in gencache.
630          */
631
632         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
633                                     aprinter);
634         if ((cache_key != NULL) &&
635             gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
636
637                 found = (strcmp(tmp, printer_not_found) != 0);
638                 if (!found) {
639                         DEBUG(4, ("Printer %s not found\n", aprinter));
640                         TALLOC_FREE(tmp);
641                         return WERR_INVALID_PRINTER_NAME;
642                 }
643                 fstrcpy(sname, tmp);
644                 TALLOC_FREE(tmp);
645         }
646
647         /* Search all sharenames first as this is easier than pulling
648            the printer_info_2 off of disk. Don't use find_service() since
649            that calls out to map_username() */
650
651         /* do another loop to look for printernames */
652         for (snum = 0; !found && snum < n_services; snum++) {
653                 const char *printer = lp_const_servicename(snum);
654
655                 /* no point going on if this is not a printer */
656                 if (!(lp_snum_ok(snum) && lp_printable(snum))) {
657                         continue;
658                 }
659
660                 /* ignore [printers] share */
661                 if (strequal(printer, "printers")) {
662                         continue;
663                 }
664
665                 fstrcpy(sname, printer);
666                 if (strequal(aprinter, printer)) {
667                         found = true;
668                         break;
669                 }
670
671                 /* no point looking up the printer object if
672                    we aren't allowing printername != sharename */
673                 if (lp_force_printername(snum)) {
674                         continue;
675                 }
676
677                 result = winreg_get_printer_internal(mem_ctx,
678                                             session_info,
679                                             msg_ctx,
680                                             sname,
681                                             &info2);
682                 if ( !W_ERROR_IS_OK(result) ) {
683                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
684                                  sname, win_errstr(result)));
685                         continue;
686                 }
687
688                 printername = strrchr(info2->printername, '\\');
689                 if (printername == NULL) {
690                         printername = info2->printername;
691                 } else {
692                         printername++;
693                 }
694
695                 if (strequal(printername, aprinter)) {
696                         found = true;
697                         break;
698                 }
699
700                 DEBUGADD(10, ("printername: %s\n", printername));
701
702                 TALLOC_FREE(info2);
703         }
704
705         if ( !found ) {
706                 if (cache_key != NULL) {
707                         gencache_set(cache_key, printer_not_found,
708                                      time(NULL)+300);
709                         TALLOC_FREE(cache_key);
710                 }
711                 DEBUGADD(4,("Printer not found\n"));
712                 return WERR_INVALID_PRINTER_NAME;
713         }
714
715         if (cache_key != NULL) {
716                 gencache_set(cache_key, sname, time(NULL)+300);
717                 TALLOC_FREE(cache_key);
718         }
719
720         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
721
722         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
723
724         return WERR_OK;
725 }
726
727 /****************************************************************************
728  Find first available printer slot. creates a printer handle for you.
729  ****************************************************************************/
730
731 static WERROR open_printer_hnd(struct pipes_struct *p,
732                                struct policy_handle *hnd,
733                                const char *name,
734                                uint32_t access_granted)
735 {
736         struct printer_handle *new_printer;
737         WERROR result;
738
739         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
740
741         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
742         if (new_printer == NULL) {
743                 return WERR_NOMEM;
744         }
745         talloc_set_destructor(new_printer, printer_entry_destructor);
746
747         /* This also steals the printer_handle on the policy_handle */
748         if (!create_policy_hnd(p, hnd, new_printer)) {
749                 TALLOC_FREE(new_printer);
750                 return WERR_INVALID_HANDLE;
751         }
752
753         /* Add to the internal list. */
754         DLIST_ADD(printers_list, new_printer);
755
756         new_printer->notify.option=NULL;
757
758         if (!set_printer_hnd_printertype(new_printer, name)) {
759                 close_printer_handle(p, hnd);
760                 return WERR_INVALID_HANDLE;
761         }
762
763         result = set_printer_hnd_name(p->mem_ctx,
764                                       get_session_info_system(),
765                                       p->msg_ctx,
766                                       new_printer, name);
767         if (!W_ERROR_IS_OK(result)) {
768                 close_printer_handle(p, hnd);
769                 return result;
770         }
771
772         new_printer->access_granted = access_granted;
773
774         DEBUG(5, ("%d printer handles active\n",
775                   (int)num_pipe_handles(p)));
776
777         return WERR_OK;
778 }
779
780 /***************************************************************************
781  check to see if the client motify handle is monitoring the notification
782  given by (notify_type, notify_field).
783  **************************************************************************/
784
785 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
786                                       uint16_t notify_field)
787 {
788         return true;
789 }
790
791 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
792                                 uint16_t notify_field)
793 {
794         struct spoolss_NotifyOption *option = p->notify.option;
795         uint32_t i, j;
796
797         /*
798          * Flags should always be zero when the change notify
799          * is registered by the client's spooler.  A user Win32 app
800          * might use the flags though instead of the NOTIFY_OPTION_INFO
801          * --jerry
802          */
803
804         if (!option) {
805                 return false;
806         }
807
808         if (p->notify.flags)
809                 return is_monitoring_event_flags(
810                         p->notify.flags, notify_type, notify_field);
811
812         for (i = 0; i < option->count; i++) {
813
814                 /* Check match for notify_type */
815
816                 if (option->types[i].type != notify_type)
817                         continue;
818
819                 /* Check match for field */
820
821                 for (j = 0; j < option->types[i].count; j++) {
822                         if (option->types[i].fields[j].field == notify_field) {
823                                 return true;
824                         }
825                 }
826         }
827
828         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
829                    p->servername, p->sharename, notify_type, notify_field));
830
831         return false;
832 }
833
834 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
835         _data->data.integer[0] = _integer; \
836         _data->data.integer[1] = 0;
837
838
839 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
840         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
841         if (!_data->data.string.string) {\
842                 _data->data.string.size = 0; \
843         } \
844         _data->data.string.size = strlen_m_term(_p) * 2;
845
846 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
847         _data->data.devmode.devmode = _devmode;
848
849 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
850         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
851         if (!_data->data.sd.sd) { \
852                 _data->data.sd.sd_size = 0; \
853         } \
854         _data->data.sd.sd_size = \
855                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
856
857 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
858                                    struct tm *t,
859                                    const char **pp,
860                                    uint32_t *plen)
861 {
862         struct spoolss_Time st;
863         uint32_t len = 16;
864         char *p;
865
866         if (!init_systemtime(&st, t)) {
867                 return;
868         }
869
870         p = talloc_array(mem_ctx, char, len);
871         if (!p) {
872                 return;
873         }
874
875         /*
876          * Systemtime must be linearized as a set of UINT16's.
877          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
878          */
879
880         SSVAL(p, 0, st.year);
881         SSVAL(p, 2, st.month);
882         SSVAL(p, 4, st.day_of_week);
883         SSVAL(p, 6, st.day);
884         SSVAL(p, 8, st.hour);
885         SSVAL(p, 10, st.minute);
886         SSVAL(p, 12, st.second);
887         SSVAL(p, 14, st.millisecond);
888
889         *pp = p;
890         *plen = len;
891 }
892
893 /* Convert a notification message to a struct spoolss_Notify */
894
895 static void notify_one_value(struct spoolss_notify_msg *msg,
896                              struct spoolss_Notify *data,
897                              TALLOC_CTX *mem_ctx)
898 {
899         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
900 }
901
902 static void notify_string(struct spoolss_notify_msg *msg,
903                           struct spoolss_Notify *data,
904                           TALLOC_CTX *mem_ctx)
905 {
906         /* The length of the message includes the trailing \0 */
907
908         data->data.string.size = msg->len * 2;
909         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
910         if (!data->data.string.string) {
911                 data->data.string.size = 0;
912                 return;
913         }
914 }
915
916 static void notify_system_time(struct spoolss_notify_msg *msg,
917                                struct spoolss_Notify *data,
918                                TALLOC_CTX *mem_ctx)
919 {
920         data->data.string.string = NULL;
921         data->data.string.size = 0;
922
923         if (msg->len != sizeof(time_t)) {
924                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
925                           msg->len));
926                 return;
927         }
928
929         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
930                                &data->data.string.string,
931                                &data->data.string.size);
932 }
933
934 struct notify2_message_table {
935         const char *name;
936         void (*fn)(struct spoolss_notify_msg *msg,
937                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
938 };
939
940 static struct notify2_message_table printer_notify_table[] = {
941         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
942         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
943         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
944         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
945         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
946         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
947         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
948         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
949         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
950         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
951         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
952         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
953         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
954         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
955         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
956         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
957         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
958         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
959         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
960 };
961
962 static struct notify2_message_table job_notify_table[] = {
963         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
964         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
965         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
966         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
967         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
968         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
969         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
970         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
971         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
972         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
973         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
974         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
975         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
976         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
977         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
978         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
979         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
980         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
981         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
982         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
983         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
984         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
985         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
986         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
987 };
988
989
990 /***********************************************************************
991  Allocate talloc context for container object
992  **********************************************************************/
993
994 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
995 {
996         if ( !ctr )
997                 return;
998
999         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1000
1001         return;
1002 }
1003
1004 /***********************************************************************
1005  release all allocated memory and zero out structure
1006  **********************************************************************/
1007
1008 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1009 {
1010         if ( !ctr )
1011                 return;
1012
1013         if ( ctr->ctx )
1014                 talloc_destroy(ctr->ctx);
1015
1016         ZERO_STRUCTP(ctr);
1017
1018         return;
1019 }
1020
1021 /***********************************************************************
1022  **********************************************************************/
1023
1024 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1025 {
1026         if ( !ctr )
1027                 return NULL;
1028
1029         return ctr->ctx;
1030 }
1031
1032 /***********************************************************************
1033  **********************************************************************/
1034
1035 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1036 {
1037         if ( !ctr || !ctr->msg_groups )
1038                 return NULL;
1039
1040         if ( idx >= ctr->num_groups )
1041                 return NULL;
1042
1043         return &ctr->msg_groups[idx];
1044
1045 }
1046
1047 /***********************************************************************
1048  How many groups of change messages do we have ?
1049  **********************************************************************/
1050
1051 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1052 {
1053         if ( !ctr )
1054                 return 0;
1055
1056         return ctr->num_groups;
1057 }
1058
1059 /***********************************************************************
1060  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1061  **********************************************************************/
1062
1063 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1064 {
1065         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1066         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1067         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1068         int                             i, new_slot;
1069
1070         if ( !ctr || !msg )
1071                 return 0;
1072
1073         /* loop over all groups looking for a matching printer name */
1074
1075         for ( i=0; i<ctr->num_groups; i++ ) {
1076                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1077                         break;
1078         }
1079
1080         /* add a new group? */
1081
1082         if ( i == ctr->num_groups ) {
1083                 ctr->num_groups++;
1084
1085                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1086                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1087                         return 0;
1088                 }
1089                 ctr->msg_groups = groups;
1090
1091                 /* clear the new entry and set the printer name */
1092
1093                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1094                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1095         }
1096
1097         /* add the change messages; 'i' is the correct index now regardless */
1098
1099         msg_grp = &ctr->msg_groups[i];
1100
1101         msg_grp->num_msgs++;
1102
1103         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1104                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1105                 return 0;
1106         }
1107         msg_grp->msgs = msg_list;
1108
1109         new_slot = msg_grp->num_msgs-1;
1110         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1111
1112         /* need to allocate own copy of data */
1113
1114         if ( msg->len != 0 )
1115                 msg_grp->msgs[new_slot].notify.data = (char *)
1116                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1117
1118         return ctr->num_groups;
1119 }
1120
1121 static void construct_info_data(struct spoolss_Notify *info_data,
1122                                 enum spoolss_NotifyType type,
1123                                 uint16_t field, int id);
1124
1125 /***********************************************************************
1126  Send a change notication message on all handles which have a call
1127  back registered
1128  **********************************************************************/
1129
1130 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1131                                   struct printer_handle *prn_hnd,
1132                                   SPOOLSS_NOTIFY_MSG *messages,
1133                                   uint32_t num_msgs,
1134                                   struct spoolss_Notify **_notifies,
1135                                   int *_count)
1136 {
1137         struct spoolss_Notify *notifies;
1138         SPOOLSS_NOTIFY_MSG *msg;
1139         int count = 0;
1140         uint32_t id;
1141         int i;
1142
1143         notifies = talloc_zero_array(mem_ctx,
1144                                      struct spoolss_Notify, num_msgs);
1145         if (!notifies) {
1146                 return ENOMEM;
1147         }
1148
1149         for (i = 0; i < num_msgs; i++) {
1150
1151                 msg = &messages[i];
1152
1153                 /* Are we monitoring this event? */
1154
1155                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1156                         continue;
1157                 }
1158
1159                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1160                            "for printer [%s]\n",
1161                            msg->type, msg->field, prn_hnd->sharename));
1162
1163                 /*
1164                  * if the is a printer notification handle and not a job
1165                  * notification type, then set the id to 0.
1166                  * Otherwise just use what was specified in the message.
1167                  *
1168                  * When registering change notification on a print server
1169                  * handle we always need to send back the id (snum) matching
1170                  * the printer for which the change took place.
1171                  * For change notify registered on a printer handle,
1172                  * this does not matter and the id should be 0.
1173                  *
1174                  * --jerry
1175                  */
1176
1177                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1178                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1179                         id = 0;
1180                 } else {
1181                         id = msg->id;
1182                 }
1183
1184                 /* Convert unix jobid to smb jobid */
1185
1186                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1187                         id = sysjob_to_jobid(msg->id);
1188
1189                         if (id == -1) {
1190                                 DEBUG(3, ("no such unix jobid %d\n",
1191                                           msg->id));
1192                                 continue;
1193                         }
1194                 }
1195
1196                 construct_info_data(&notifies[count],
1197                                     msg->type, msg->field, id);
1198
1199                 switch(msg->type) {
1200                 case PRINTER_NOTIFY_TYPE:
1201                         if (printer_notify_table[msg->field].fn) {
1202                                 printer_notify_table[msg->field].fn(msg,
1203                                                 &notifies[count], mem_ctx);
1204                         }
1205                         break;
1206
1207                 case JOB_NOTIFY_TYPE:
1208                         if (job_notify_table[msg->field].fn) {
1209                                 job_notify_table[msg->field].fn(msg,
1210                                                 &notifies[count], mem_ctx);
1211                         }
1212                         break;
1213
1214                 default:
1215                         DEBUG(5, ("Unknown notification type %d\n",
1216                                   msg->type));
1217                         continue;
1218                 }
1219
1220                 count++;
1221         }
1222
1223         *_notifies = notifies;
1224         *_count = count;
1225
1226         return 0;
1227 }
1228
1229 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1230                                 struct printer_handle *prn_hnd,
1231                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1232 {
1233         struct spoolss_Notify *notifies;
1234         int count = 0;
1235         union spoolss_ReplyPrinterInfo info;
1236         struct spoolss_NotifyInfo info0;
1237         uint32_t reply_result;
1238         NTSTATUS status;
1239         WERROR werr;
1240         int ret;
1241
1242         /* Is there notification on this handle? */
1243         if (prn_hnd->notify.cli_chan == NULL ||
1244             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1245             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1246             prn_hnd->notify.cli_chan->active_connections == 0) {
1247                 return 0;
1248         }
1249
1250         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1251                    prn_hnd->servername, prn_hnd->sharename));
1252
1253         /* For this printer? Print servers always receive notifications. */
1254         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1255             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1256                 return 0;
1257         }
1258
1259         DEBUG(10,("Our printer\n"));
1260
1261         /* build the array of change notifications */
1262         ret = build_notify2_messages(mem_ctx, prn_hnd,
1263                                      msg_group->msgs,
1264                                      msg_group->num_msgs,
1265                                      &notifies, &count);
1266         if (ret) {
1267                 return ret;
1268         }
1269
1270         info0.version   = 0x2;
1271         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1272         info0.count     = count;
1273         info0.notifies  = notifies;
1274
1275         info.info0 = &info0;
1276
1277         status = dcerpc_spoolss_RouterReplyPrinterEx(
1278                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1279                                 mem_ctx,
1280                                 &prn_hnd->notify.cli_hnd,
1281                                 prn_hnd->notify.change, /* color */
1282                                 prn_hnd->notify.flags,
1283                                 &reply_result,
1284                                 0, /* reply_type, must be 0 */
1285                                 info, &werr);
1286         if (!NT_STATUS_IS_OK(status)) {
1287                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1288                           "failed: %s\n",
1289                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1290                           nt_errstr(status)));
1291                 werr = ntstatus_to_werror(status);
1292         } else if (!W_ERROR_IS_OK(werr)) {
1293                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1294                           "failed: %s\n",
1295                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1296                           win_errstr(werr)));
1297         }
1298         switch (reply_result) {
1299         case 0:
1300                 break;
1301         case PRINTER_NOTIFY_INFO_DISCARDED:
1302         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1303         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1304                 break;
1305         default:
1306                 break;
1307         }
1308
1309         return 0;
1310 }
1311
1312 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1313 {
1314         struct printer_handle    *p;
1315         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1316         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1317         int ret;
1318
1319         if ( !msg_group ) {
1320                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1321                 return;
1322         }
1323
1324         if (!msg_group->msgs) {
1325                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1326                 return;
1327         }
1328
1329         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1330
1331         /* loop over all printers */
1332
1333         for (p = printers_list; p; p = p->next) {
1334                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1335                 if (ret) {
1336                         goto done;
1337                 }
1338         }
1339
1340 done:
1341         DEBUG(8,("send_notify2_changes: Exit...\n"));
1342         return;
1343 }
1344
1345 /***********************************************************************
1346  **********************************************************************/
1347
1348 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1349 {
1350
1351         uint32_t tv_sec, tv_usec;
1352         size_t offset = 0;
1353
1354         /* Unpack message */
1355
1356         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1357                              msg->printer);
1358
1359         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1360                                 &tv_sec, &tv_usec,
1361                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1362
1363         if (msg->len == 0)
1364                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1365                            &msg->notify.value[0], &msg->notify.value[1]);
1366         else
1367                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1368                            &msg->len, &msg->notify.data);
1369
1370         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1371                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1372
1373         tv->tv_sec = tv_sec;
1374         tv->tv_usec = tv_usec;
1375
1376         if (msg->len == 0)
1377                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1378                           msg->notify.value[1]));
1379         else
1380                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1381
1382         return true;
1383 }
1384
1385 /********************************************************************
1386  Receive a notify2 message list
1387  ********************************************************************/
1388
1389 static void receive_notify2_message_list(struct messaging_context *msg,
1390                                          void *private_data,
1391                                          uint32_t msg_type,
1392                                          struct server_id server_id,
1393                                          DATA_BLOB *data)
1394 {
1395         size_t                  msg_count, i;
1396         char                    *buf = (char *)data->data;
1397         char                    *msg_ptr;
1398         size_t                  msg_len;
1399         SPOOLSS_NOTIFY_MSG      notify;
1400         SPOOLSS_NOTIFY_MSG_CTR  messages;
1401         int                     num_groups;
1402
1403         if (data->length < 4) {
1404                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1405                 return;
1406         }
1407
1408         msg_count = IVAL(buf, 0);
1409         msg_ptr = buf + 4;
1410
1411         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1412
1413         if (msg_count == 0) {
1414                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1415                 return;
1416         }
1417
1418         /* initialize the container */
1419
1420         ZERO_STRUCT( messages );
1421         notify_msg_ctr_init( &messages );
1422
1423         /*
1424          * build message groups for each printer identified
1425          * in a change_notify msg.  Remember that a PCN message
1426          * includes the handle returned for the srv_spoolss_replyopenprinter()
1427          * call.  Therefore messages are grouped according to printer handle.
1428          */
1429
1430         for ( i=0; i<msg_count; i++ ) {
1431                 struct timeval msg_tv;
1432
1433                 if (msg_ptr + 4 - buf > data->length) {
1434                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1435                         return;
1436                 }
1437
1438                 msg_len = IVAL(msg_ptr,0);
1439                 msg_ptr += 4;
1440
1441                 if (msg_ptr + msg_len - buf > data->length) {
1442                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1443                         return;
1444                 }
1445
1446                 /* unpack messages */
1447
1448                 ZERO_STRUCT( notify );
1449                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1450                 msg_ptr += msg_len;
1451
1452                 /* add to correct list in container */
1453
1454                 notify_msg_ctr_addmsg( &messages, &notify );
1455
1456                 /* free memory that might have been allocated by notify2_unpack_msg() */
1457
1458                 if ( notify.len != 0 )
1459                         SAFE_FREE( notify.notify.data );
1460         }
1461
1462         /* process each group of messages */
1463
1464         num_groups = notify_msg_ctr_numgroups( &messages );
1465         for ( i=0; i<num_groups; i++ )
1466                 send_notify2_changes( &messages, i );
1467
1468
1469         /* cleanup */
1470
1471         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1472                 (uint32_t)msg_count ));
1473
1474         notify_msg_ctr_destroy( &messages );
1475
1476         return;
1477 }
1478
1479 /********************************************************************
1480  Send a message to ourself about new driver being installed
1481  so we can upgrade the information for each printer bound to this
1482  driver
1483  ********************************************************************/
1484
1485 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1486                                             struct messaging_context *msg_ctx)
1487 {
1488         int len = strlen(drivername);
1489
1490         if (!len)
1491                 return false;
1492
1493         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1494                 drivername));
1495
1496         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1497                            MSG_PRINTER_DRVUPGRADE,
1498                            (const uint8_t *)drivername, len+1);
1499
1500         return true;
1501 }
1502
1503 void srv_spoolss_cleanup(void)
1504 {
1505         struct printer_session_counter *session_counter;
1506
1507         for (session_counter = counter_list;
1508              session_counter != NULL;
1509              session_counter = counter_list) {
1510                 DLIST_REMOVE(counter_list, session_counter);
1511                 TALLOC_FREE(session_counter);
1512         }
1513 }
1514
1515 /**********************************************************************
1516  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1517  over all printers, upgrading ones as necessary
1518  **********************************************************************/
1519
1520 void do_drv_upgrade_printer(struct messaging_context *msg,
1521                             void *private_data,
1522                             uint32_t msg_type,
1523                             struct server_id server_id,
1524                             DATA_BLOB *data)
1525 {
1526         TALLOC_CTX *tmp_ctx;
1527         const struct auth_session_info *session_info = get_session_info_system();
1528         struct spoolss_PrinterInfo2 *pinfo2;
1529         WERROR result;
1530         const char *drivername;
1531         int snum;
1532         int n_services = lp_numservices();
1533         struct dcerpc_binding_handle *b = NULL;
1534
1535         tmp_ctx = talloc_new(NULL);
1536         if (!tmp_ctx) return;
1537
1538         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1539         if (!drivername) {
1540                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1541                 goto done;
1542         }
1543
1544         DEBUG(10, ("do_drv_upgrade_printer: "
1545                    "Got message for new driver [%s]\n", drivername));
1546
1547         /* Iterate the printer list */
1548
1549         for (snum = 0; snum < n_services; snum++) {
1550                 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1551                         continue;
1552                 }
1553
1554                 /* ignore [printers] share */
1555                 if (strequal(lp_const_servicename(snum), "printers")) {
1556                         continue;
1557                 }
1558
1559                 if (b == NULL) {
1560                         result = winreg_printer_binding_handle(tmp_ctx,
1561                                                                session_info,
1562                                                                msg,
1563                                                                &b);
1564                         if (!W_ERROR_IS_OK(result)) {
1565                                 break;
1566                         }
1567                 }
1568
1569                 result = winreg_get_printer(tmp_ctx, b,
1570                                             lp_const_servicename(snum),
1571                                             &pinfo2);
1572
1573                 if (!W_ERROR_IS_OK(result)) {
1574                         continue;
1575                 }
1576
1577                 if (!pinfo2->drivername) {
1578                         continue;
1579                 }
1580
1581                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1582                         continue;
1583                 }
1584
1585                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1586
1587                 /* all we care about currently is the change_id */
1588                 result = winreg_printer_update_changeid(tmp_ctx, b,
1589                                                         pinfo2->printername);
1590
1591                 if (!W_ERROR_IS_OK(result)) {
1592                         DEBUG(3, ("do_drv_upgrade_printer: "
1593                                   "Failed to update changeid [%s]\n",
1594                                   win_errstr(result)));
1595                 }
1596         }
1597
1598         /* all done */
1599 done:
1600         talloc_free(tmp_ctx);
1601 }
1602
1603 /********************************************************************
1604  Update the cache for all printq's with a registered client
1605  connection
1606  ********************************************************************/
1607
1608 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1609 {
1610         struct printer_handle *printer = printers_list;
1611         int snum;
1612
1613         /* loop through all printers and update the cache where
1614            a client is connected */
1615         while (printer) {
1616                 if ((printer->printer_type == SPLHND_PRINTER) &&
1617                     ((printer->notify.cli_chan != NULL) &&
1618                      (printer->notify.cli_chan->active_connections > 0))) {
1619                         snum = print_queue_snum(printer->sharename);
1620                         print_queue_status(msg_ctx, snum, NULL, NULL);
1621                 }
1622
1623                 printer = printer->next;
1624         }
1625
1626         return;
1627 }
1628
1629 /****************************************************************
1630  _spoolss_OpenPrinter
1631 ****************************************************************/
1632
1633 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1634                             struct spoolss_OpenPrinter *r)
1635 {
1636         struct spoolss_OpenPrinterEx e;
1637         struct spoolss_UserLevel1 level1;
1638         WERROR werr;
1639
1640         ZERO_STRUCT(level1);
1641
1642         e.in.printername        = r->in.printername;
1643         e.in.datatype           = r->in.datatype;
1644         e.in.devmode_ctr        = r->in.devmode_ctr;
1645         e.in.access_mask        = r->in.access_mask;
1646         e.in.userlevel_ctr.level                = 1;
1647         e.in.userlevel_ctr.user_info.level1     = &level1;
1648
1649         e.out.handle            = r->out.handle;
1650
1651         werr = _spoolss_OpenPrinterEx(p, &e);
1652
1653         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1654                 /* OpenPrinterEx returns this for a bad
1655                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1656                  * instead.
1657                  */
1658                 werr = WERR_INVALID_PRINTER_NAME;
1659         }
1660
1661         return werr;
1662 }
1663
1664 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1665                               struct spoolss_DeviceMode *orig,
1666                               struct spoolss_DeviceMode **dest)
1667 {
1668         struct spoolss_DeviceMode *dm;
1669
1670         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1671         if (!dm) {
1672                 return WERR_NOMEM;
1673         }
1674
1675         /* copy all values, then duplicate strings and structs */
1676         *dm = *orig;
1677
1678         dm->devicename = talloc_strdup(dm, orig->devicename);
1679         if (!dm->devicename) {
1680                 return WERR_NOMEM;
1681         }
1682         dm->formname = talloc_strdup(dm, orig->formname);
1683         if (!dm->formname) {
1684                 return WERR_NOMEM;
1685         }
1686         if (orig->driverextra_data.data) {
1687                 dm->driverextra_data.data =
1688                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1689                                         orig->driverextra_data.length);
1690                 if (!dm->driverextra_data.data) {
1691                         return WERR_NOMEM;
1692                 }
1693         }
1694
1695         *dest = dm;
1696         return WERR_OK;
1697 }
1698
1699 /****************************************************************
1700  _spoolss_OpenPrinterEx
1701 ****************************************************************/
1702
1703 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1704                               struct spoolss_OpenPrinterEx *r)
1705 {
1706         int snum;
1707         char *raddr;
1708         char *rhost;
1709         struct printer_handle *Printer=NULL;
1710         WERROR result;
1711         int rc;
1712
1713         if (!r->in.printername) {
1714                 return WERR_INVALID_PARAM;
1715         }
1716
1717         if (!*r->in.printername) {
1718                 return WERR_INVALID_PARAM;
1719         }
1720
1721         if (r->in.userlevel_ctr.level > 3) {
1722                 return WERR_INVALID_PARAM;
1723         }
1724         if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1725             (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1726             (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1727                 return WERR_INVALID_PARAM;
1728         }
1729
1730         /* some sanity check because you can open a printer or a print server */
1731         /* aka: \\server\printer or \\server */
1732
1733         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1734
1735         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1736         if (!W_ERROR_IS_OK(result)) {
1737                 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1738                         "for printer %s\n", r->in.printername));
1739                 ZERO_STRUCTP(r->out.handle);
1740                 return result;
1741         }
1742
1743         Printer = find_printer_index_by_hnd(p, r->out.handle);
1744         if ( !Printer ) {
1745                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1746                         "handle we created for printer %s\n", r->in.printername));
1747                 close_printer_handle(p, r->out.handle);
1748                 ZERO_STRUCTP(r->out.handle);
1749                 return WERR_INVALID_PARAM;
1750         }
1751
1752         /*
1753          * First case: the user is opening the print server:
1754          *
1755          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1756          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1757          *
1758          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1759          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1760          * or if the user is listed in the smb.conf printer admin parameter.
1761          *
1762          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1763          * client view printer folder, but does not show the MSAPW.
1764          *
1765          * Note: this test needs code to check access rights here too. Jeremy
1766          * could you look at this?
1767          *
1768          * Second case: the user is opening a printer:
1769          * NT doesn't let us connect to a printer if the connecting user
1770          * doesn't have print permission.
1771          *
1772          * Third case: user is opening a Port Monitor
1773          * access checks same as opening a handle to the print server.
1774          */
1775
1776         switch (Printer->printer_type )
1777         {
1778         case SPLHND_SERVER:
1779         case SPLHND_PORTMON_TCP:
1780         case SPLHND_PORTMON_LOCAL:
1781                 /* Printserver handles use global struct... */
1782
1783                 snum = -1;
1784
1785                 /* Map standard access rights to object specific access rights */
1786
1787                 se_map_standard(&r->in.access_mask,
1788                                 &printserver_std_mapping);
1789
1790                 /* Deny any object specific bits that don't apply to print
1791                    servers (i.e printer and job specific bits) */
1792
1793                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1794
1795                 if (r->in.access_mask &
1796                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1797                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1798                         close_printer_handle(p, r->out.handle);
1799                         ZERO_STRUCTP(r->out.handle);
1800                         return WERR_ACCESS_DENIED;
1801                 }
1802
1803                 /* Allow admin access */
1804
1805                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1806                 {
1807                         if (!lp_ms_add_printer_wizard()) {
1808                                 close_printer_handle(p, r->out.handle);
1809                                 ZERO_STRUCTP(r->out.handle);
1810                                 return WERR_ACCESS_DENIED;
1811                         }
1812
1813                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1814                            and not a printer admin, then fail */
1815
1816                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1817                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1818                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1819                                                 p->session_info->security_token)) {
1820                                 close_printer_handle(p, r->out.handle);
1821                                 ZERO_STRUCTP(r->out.handle);
1822                                 DEBUG(3,("access DENIED as user is not root, "
1823                                         "has no printoperator privilege, "
1824                                         "not a member of the printoperator builtin group and "
1825                                         "is not in printer admin list"));
1826                                 return WERR_ACCESS_DENIED;
1827                         }
1828
1829                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1830                 }
1831                 else
1832                 {
1833                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1834                 }
1835
1836                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1837                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1838
1839                 /* We fall through to return WERR_OK */
1840                 break;
1841
1842         case SPLHND_PRINTER:
1843                 /* NT doesn't let us connect to a printer if the connecting user
1844                    doesn't have print permission.  */
1845
1846                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1847                         close_printer_handle(p, r->out.handle);
1848                         ZERO_STRUCTP(r->out.handle);
1849                         return WERR_BADFID;
1850                 }
1851
1852                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1853                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1854                 }
1855
1856                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1857
1858                 /* map an empty access mask to the minimum access mask */
1859                 if (r->in.access_mask == 0x0)
1860                         r->in.access_mask = PRINTER_ACCESS_USE;
1861
1862                 /*
1863                  * If we are not serving the printer driver for this printer,
1864                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1865                  * will keep NT clients happy  --jerry
1866                  */
1867
1868                 if (lp_use_client_driver(snum)
1869                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1870                 {
1871                         r->in.access_mask = PRINTER_ACCESS_USE;
1872                 }
1873
1874                 /* check smb.conf parameters and the the sec_desc */
1875                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1876                                                          p->mem_ctx);
1877                 if (raddr == NULL) {
1878                         return WERR_NOMEM;
1879                 }
1880
1881                 rc = get_remote_hostname(p->remote_address,
1882                                          &rhost,
1883                                          p->mem_ctx);
1884                 if (rc < 0) {
1885                         return WERR_NOMEM;
1886                 }
1887                 if (strequal(rhost, "UNKNOWN")) {
1888                         rhost = raddr;
1889                 }
1890
1891                 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1892                                   rhost, raddr)) {
1893                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1894                         ZERO_STRUCTP(r->out.handle);
1895                         return WERR_ACCESS_DENIED;
1896                 }
1897
1898                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1899                                    p->session_info->security_token, snum) ||
1900                     !W_ERROR_IS_OK(print_access_check(p->session_info,
1901                                                       p->msg_ctx,
1902                                                       snum,
1903                                                       r->in.access_mask))) {
1904                         DEBUG(3, ("access DENIED for printer open\n"));
1905                         close_printer_handle(p, r->out.handle);
1906                         ZERO_STRUCTP(r->out.handle);
1907                         return WERR_ACCESS_DENIED;
1908                 }
1909
1910                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1911                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1912                         close_printer_handle(p, r->out.handle);
1913                         ZERO_STRUCTP(r->out.handle);
1914                         return WERR_ACCESS_DENIED;
1915                 }
1916
1917                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1918                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1919                 else
1920                         r->in.access_mask = PRINTER_ACCESS_USE;
1921
1922                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1923                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1924
1925                 winreg_create_printer_internal(p->mem_ctx,
1926                                       get_session_info_system(),
1927                                       p->msg_ctx,
1928                                       lp_const_servicename(snum));
1929
1930                 break;
1931
1932         default:
1933                 /* sanity check to prevent programmer error */
1934                 ZERO_STRUCTP(r->out.handle);
1935                 return WERR_BADFID;
1936         }
1937
1938         Printer->access_granted = r->in.access_mask;
1939
1940         /*
1941          * If the client sent a devmode in the OpenPrinter() call, then
1942          * save it here in case we get a job submission on this handle
1943          */
1944
1945          if ((Printer->printer_type != SPLHND_SERVER)
1946           && (r->in.devmode_ctr.devmode != NULL)) {
1947                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1948                                 &Printer->devmode);
1949          }
1950
1951         return WERR_OK;
1952 }
1953
1954 /****************************************************************
1955  _spoolss_ClosePrinter
1956 ****************************************************************/
1957
1958 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1959                              struct spoolss_ClosePrinter *r)
1960 {
1961         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1962
1963         if (Printer && Printer->document_started) {
1964                 struct spoolss_EndDocPrinter e;
1965
1966                 e.in.handle = r->in.handle;
1967
1968                 _spoolss_EndDocPrinter(p, &e);
1969         }
1970
1971         if (!close_printer_handle(p, r->in.handle))
1972                 return WERR_BADFID;
1973
1974         /* clear the returned printer handle.  Observed behavior
1975            from Win2k server.  Don't think this really matters.
1976            Previous code just copied the value of the closed
1977            handle.    --jerry */
1978
1979         ZERO_STRUCTP(r->out.handle);
1980
1981         return WERR_OK;
1982 }
1983
1984 /****************************************************************
1985  _spoolss_DeletePrinter
1986 ****************************************************************/
1987
1988 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1989                               struct spoolss_DeletePrinter *r)
1990 {
1991         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1992         WERROR result;
1993         int snum;
1994
1995         if (Printer && Printer->document_started) {
1996                 struct spoolss_EndDocPrinter e;
1997
1998                 e.in.handle = r->in.handle;
1999
2000                 _spoolss_EndDocPrinter(p, &e);
2001         }
2002
2003         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2004                 winreg_delete_printer_key_internal(p->mem_ctx,
2005                                           get_session_info_system(),
2006                                           p->msg_ctx,
2007                                           lp_const_servicename(snum),
2008                                           "");
2009         }
2010
2011         result = delete_printer_handle(p, r->in.handle);
2012
2013         return result;
2014 }
2015
2016 /*******************************************************************
2017  * static function to lookup the version id corresponding to an
2018  * long architecture string
2019  ******************************************************************/
2020
2021 static const struct print_architecture_table_node archi_table[]= {
2022
2023         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2024         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2025         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2026         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2027         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2028         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2029         {"Windows x64",          SPL_ARCH_X64,          3 },
2030         {NULL,                   "",            -1 }
2031 };
2032
2033 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2034                                    SPOOLSS_DRIVER_VERSION_NT35,
2035                                    SPOOLSS_DRIVER_VERSION_NT4,
2036                                    SPOOLSS_DRIVER_VERSION_200X,
2037                                    -1};
2038
2039 static int get_version_id(const char *arch)
2040 {
2041         int i;
2042
2043         for (i=0; archi_table[i].long_archi != NULL; i++)
2044         {
2045                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2046                         return (archi_table[i].version);
2047         }
2048
2049         return -1;
2050 }
2051
2052 /****************************************************************
2053  _spoolss_DeletePrinterDriver
2054 ****************************************************************/
2055
2056 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2057                                     struct spoolss_DeletePrinterDriver *r)
2058 {
2059
2060         struct spoolss_DriverInfo8 *info = NULL;
2061         int                             version;
2062         WERROR                          status;
2063         struct dcerpc_binding_handle *b;
2064         TALLOC_CTX *tmp_ctx = NULL;
2065         int i;
2066         bool found;
2067
2068         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2069            and not a printer admin, then fail */
2070
2071         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2072             !security_token_has_privilege(p->session_info->security_token,
2073                                           SEC_PRIV_PRINT_OPERATOR)) {
2074                 return WERR_ACCESS_DENIED;
2075         }
2076
2077         /* check that we have a valid driver name first */
2078
2079         if ((version = get_version_id(r->in.architecture)) == -1) {
2080                 return WERR_INVALID_ENVIRONMENT;
2081         }
2082
2083         tmp_ctx = talloc_new(p->mem_ctx);
2084         if (!tmp_ctx) {
2085                 return WERR_NOMEM;
2086         }
2087
2088         status = winreg_printer_binding_handle(tmp_ctx,
2089                                                get_session_info_system(),
2090                                                p->msg_ctx,
2091                                                &b);
2092         if (!W_ERROR_IS_OK(status)) {
2093                 goto done;
2094         }
2095
2096         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2097                 status = winreg_get_driver(tmp_ctx, b,
2098                                            r->in.architecture, r->in.driver,
2099                                            drv_cversion[i], &info);
2100                 if (!W_ERROR_IS_OK(status)) {
2101                         DEBUG(5, ("skipping del of driver with version %d\n",
2102                                   drv_cversion[i]));
2103                         continue;
2104                 }
2105                 found = true;
2106
2107                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2108                         status = WERR_PRINTER_DRIVER_IN_USE;
2109                         goto done;
2110                 }
2111
2112                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2113                 if (!W_ERROR_IS_OK(status)) {
2114                         DEBUG(0, ("failed del of driver with version %d\n",
2115                                   drv_cversion[i]));
2116                         goto done;
2117                 }
2118         }
2119         if (found == false) {
2120                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2121                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2122         } else {
2123                 status = WERR_OK;
2124         }
2125
2126 done:
2127         talloc_free(tmp_ctx);
2128
2129         return status;
2130 }
2131
2132 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2133                                   struct pipes_struct *p,
2134                                   struct spoolss_DeletePrinterDriverEx *r,
2135                                   struct dcerpc_binding_handle *b,
2136                                   struct spoolss_DriverInfo8 *info)
2137 {
2138         WERROR status;
2139         bool delete_files;
2140
2141         if (printer_driver_in_use(mem_ctx, b, info)) {
2142                 status = WERR_PRINTER_DRIVER_IN_USE;
2143                 goto done;
2144         }
2145
2146         /*
2147          * we have a couple of cases to consider.
2148          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2149          *     then the delete should fail if **any** files overlap with
2150          *     other drivers
2151          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2152          *     non-overlapping files
2153          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2154          *     are set, then do not delete any files
2155          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2156          */
2157
2158         delete_files = r->in.delete_flags
2159                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2160
2161
2162         if (delete_files) {
2163                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2164                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2165                         status = WERR_PRINTER_DRIVER_IN_USE;
2166                         goto done;
2167                 }
2168                 /*
2169                  * printer_driver_files_in_use() has trimmed overlapping files
2170                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2171                  */
2172         }
2173
2174
2175         status = winreg_del_driver(mem_ctx, b, info, info->version);
2176         if (!W_ERROR_IS_OK(status)) {
2177                 goto done;
2178         }
2179
2180         /*
2181          * now delete any associated files if delete_files is
2182          * true. Even if this part failes, we return succes
2183          * because the driver doesn not exist any more
2184          */
2185         if (delete_files) {
2186                 delete_driver_files(p->session_info, info);
2187         }
2188
2189 done:
2190         return status;
2191 }
2192
2193 /****************************************************************
2194  _spoolss_DeletePrinterDriverEx
2195 ****************************************************************/
2196
2197 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2198                                       struct spoolss_DeletePrinterDriverEx *r)
2199 {
2200         struct spoolss_DriverInfo8 *info = NULL;
2201         WERROR                          status;
2202         struct dcerpc_binding_handle *b;
2203         TALLOC_CTX *tmp_ctx = NULL;
2204         int i;
2205         bool found;
2206
2207         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2208            and not a printer admin, then fail */
2209
2210         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2211             !security_token_has_privilege(p->session_info->security_token,
2212                                           SEC_PRIV_PRINT_OPERATOR)) {
2213                 return WERR_ACCESS_DENIED;
2214         }
2215
2216         /* check that we have a valid driver name first */
2217         if (get_version_id(r->in.architecture) == -1) {
2218                 /* this is what NT returns */
2219                 return WERR_INVALID_ENVIRONMENT;
2220         }
2221
2222         tmp_ctx = talloc_new(p->mem_ctx);
2223         if (!tmp_ctx) {
2224                 return WERR_NOMEM;
2225         }
2226
2227         status = winreg_printer_binding_handle(tmp_ctx,
2228                                                get_session_info_system(),
2229                                                p->msg_ctx,
2230                                                &b);
2231         if (!W_ERROR_IS_OK(status)) {
2232                 goto done;
2233         }
2234
2235         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2236                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2237                  && (drv_cversion[i] != r->in.version)) {
2238                         continue;
2239                 }
2240
2241                 /* check if a driver with this version exists before delete */
2242                 status = winreg_get_driver(tmp_ctx, b,
2243                                            r->in.architecture, r->in.driver,
2244                                            drv_cversion[i], &info);
2245                 if (!W_ERROR_IS_OK(status)) {
2246                         DEBUG(5, ("skipping del of driver with version %d\n",
2247                                   drv_cversion[i]));
2248                         continue;
2249                 }
2250                 found = true;
2251
2252                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2253                 if (!W_ERROR_IS_OK(status)) {
2254                         DEBUG(0, ("failed to delete driver with version %d\n",
2255                                   drv_cversion[i]));
2256                         goto done;
2257                 }
2258         }
2259         if (found == false) {
2260                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2261                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2262         } else {
2263                 status = WERR_OK;
2264         }
2265
2266 done:
2267         talloc_free(tmp_ctx);
2268         return status;
2269 }
2270
2271
2272 /********************************************************************
2273  GetPrinterData on a printer server Handle.
2274 ********************************************************************/
2275
2276 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2277                                             const char *value,
2278                                             enum winreg_Type *type,
2279                                             union spoolss_PrinterData *data)
2280 {
2281         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2282
2283         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2284                 *type = REG_DWORD;
2285                 SIVAL(&data->value, 0, 0x00);
2286                 return WERR_OK;
2287         }
2288
2289         if (!strcasecmp_m(value, "BeepEnabled")) {
2290                 *type = REG_DWORD;
2291                 SIVAL(&data->value, 0, 0x00);
2292                 return WERR_OK;
2293         }
2294
2295         if (!strcasecmp_m(value, "EventLog")) {
2296                 *type = REG_DWORD;
2297                 /* formally was 0x1b */
2298                 SIVAL(&data->value, 0, 0x00);
2299                 return WERR_OK;
2300         }
2301
2302         if (!strcasecmp_m(value, "NetPopup")) {
2303                 *type = REG_DWORD;
2304                 SIVAL(&data->value, 0, 0x00);
2305                 return WERR_OK;
2306         }
2307
2308         if (!strcasecmp_m(value, "MajorVersion")) {
2309                 *type = REG_DWORD;
2310
2311                 /* Windows NT 4.0 seems to not allow uploading of drivers
2312                    to a server that reports 0x3 as the MajorVersion.
2313                    need to investigate more how Win2k gets around this .
2314                    -- jerry */
2315
2316                 if (RA_WINNT == get_remote_arch()) {
2317                         SIVAL(&data->value, 0, 0x02);
2318                 } else {
2319                         SIVAL(&data->value, 0, 0x03);
2320                 }
2321
2322                 return WERR_OK;
2323         }
2324
2325         if (!strcasecmp_m(value, "MinorVersion")) {
2326                 *type = REG_DWORD;
2327                 SIVAL(&data->value, 0, 0x00);
2328                 return WERR_OK;
2329         }
2330
2331         /* REG_BINARY
2332          *  uint32_t size        = 0x114
2333          *  uint32_t major       = 5
2334          *  uint32_t minor       = [0|1]
2335          *  uint32_t build       = [2195|2600]
2336          *  extra unicode string = e.g. "Service Pack 3"
2337          */
2338         if (!strcasecmp_m(value, "OSVersion")) {
2339                 DATA_BLOB blob;
2340                 enum ndr_err_code ndr_err;
2341                 struct spoolss_OSVersion os;
2342
2343                 os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
2344                                                       "spoolss", "os_major", 5);
2345                                                       /* Windows 2000 == 5.0 */
2346                 os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
2347                                                       "spoolss", "os_minor", 0);
2348                 os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
2349                                                       "spoolss", "os_build", 2195);
2350                 os.extra_string         = "";   /* leave extra string empty */
2351
2352                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2353                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2354                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2355                         return WERR_GENERAL_FAILURE;
2356                 }
2357
2358                 if (DEBUGLEVEL >= 10) {
2359                         NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2360                 }
2361
2362                 *type = REG_BINARY;
2363                 data->binary = blob;
2364
2365                 return WERR_OK;
2366         }
2367
2368
2369         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2370                 *type = REG_SZ;
2371
2372                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2373                 W_ERROR_HAVE_NO_MEMORY(data->string);
2374
2375                 return WERR_OK;
2376         }
2377
2378         if (!strcasecmp_m(value, "Architecture")) {
2379                 *type = REG_SZ;
2380                 data->string = talloc_strdup(mem_ctx,
2381                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2382                 W_ERROR_HAVE_NO_MEMORY(data->string);
2383
2384                 return WERR_OK;
2385         }
2386
2387         if (!strcasecmp_m(value, "DsPresent")) {
2388                 *type = REG_DWORD;
2389
2390                 /* only show the publish check box if we are a
2391                    member of a AD domain */
2392
2393                 if (lp_security() == SEC_ADS) {
2394                         SIVAL(&data->value, 0, 0x01);
2395                 } else {
2396                         SIVAL(&data->value, 0, 0x00);
2397                 }
2398                 return WERR_OK;
2399         }
2400
2401         if (!strcasecmp_m(value, "DNSMachineName")) {
2402                 const char *hostname = get_mydnsfullname();
2403
2404                 if (!hostname) {
2405                         return WERR_BADFILE;
2406                 }
2407
2408                 *type = REG_SZ;
2409                 data->string = talloc_strdup(mem_ctx, hostname);
2410                 W_ERROR_HAVE_NO_MEMORY(data->string);
2411
2412                 return WERR_OK;
2413         }
2414
2415         *type = REG_NONE;
2416
2417         return WERR_INVALID_PARAM;
2418 }
2419
2420 /****************************************************************
2421  _spoolss_GetPrinterData
2422 ****************************************************************/
2423
2424 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2425                                struct spoolss_GetPrinterData *r)
2426 {
2427         struct spoolss_GetPrinterDataEx r2;
2428
2429         r2.in.handle            = r->in.handle;
2430         r2.in.key_name          = "PrinterDriverData";
2431         r2.in.value_name        = r->in.value_name;
2432         r2.in.offered           = r->in.offered;
2433         r2.out.type             = r->out.type;
2434         r2.out.data             = r->out.data;
2435         r2.out.needed           = r->out.needed;
2436
2437         return _spoolss_GetPrinterDataEx(p, &r2);
2438 }
2439
2440 /*********************************************************
2441  Connect to the client machine.
2442 **********************************************************/
2443
2444 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2445                                       struct sockaddr_storage *client_ss, const char *remote_machine)
2446 {
2447         NTSTATUS ret;
2448         struct sockaddr_storage rm_addr;
2449         char addr[INET6_ADDRSTRLEN];
2450
2451         if ( is_zero_addr(client_ss) ) {
2452                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2453                         remote_machine));
2454                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2455                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2456                         return false;
2457                 }
2458                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2459         } else {
2460                 rm_addr = *client_ss;
2461                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2462                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2463                         addr));
2464         }
2465
2466         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2467                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2468                         addr));
2469                 return false;
2470         }
2471
2472         /* setup the connection */
2473         ret = cli_full_connection( pp_cli, lp_netbios_name(), remote_machine,
2474                 &rm_addr, 0, "IPC$", "IPC",
2475                 "", /* username */
2476                 "", /* domain */
2477                 "", /* password */
2478                 0, lp_client_signing());
2479
2480         if ( !NT_STATUS_IS_OK( ret ) ) {
2481                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2482                         remote_machine ));
2483                 return false;
2484         }
2485
2486         if ( smbXcli_conn_protocol((*pp_cli)->conn) != PROTOCOL_NT1 ) {
2487                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2488                 cli_shutdown(*pp_cli);
2489                 return false;
2490         }
2491
2492         /*
2493          * Ok - we have an anonymous connection to the IPC$ share.
2494          * Now start the NT Domain stuff :-).
2495          */
2496
2497         ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2498         if (!NT_STATUS_IS_OK(ret)) {
2499                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2500                         remote_machine, nt_errstr(ret)));
2501                 cli_shutdown(*pp_cli);
2502                 return false;
2503         }
2504
2505         return true;
2506 }
2507
2508 /***************************************************************************
2509  Connect to the client.
2510 ****************************************************************************/
2511
2512 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2513                                         uint32_t localprinter,
2514                                         enum winreg_Type type,
2515                                         struct policy_handle *handle,
2516                                         struct notify_back_channel **_chan,
2517                                         struct sockaddr_storage *client_ss,
2518                                         struct messaging_context *msg_ctx)
2519 {
2520         WERROR result;
2521         NTSTATUS status;
2522         struct notify_back_channel *chan;
2523
2524         for (chan = back_channels; chan; chan = chan->next) {
2525                 if (memcmp(&chan->client_address, client_ss,
2526                            sizeof(struct sockaddr_storage)) == 0) {
2527                         break;
2528                 }
2529         }
2530
2531         /*
2532          * If it's the first connection, contact the client
2533          * and connect to the IPC$ share anonymously
2534          */
2535         if (!chan) {
2536                 fstring unix_printer;
2537
2538                 /* the +2 is to strip the leading 2 backslashs */
2539                 fstrcpy(unix_printer, printer + 2);
2540
2541                 chan = talloc_zero(NULL, struct notify_back_channel);
2542                 if (!chan) {
2543                         return false;
2544                 }
2545                 chan->client_address = *client_ss;
2546
2547                 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2548                         TALLOC_FREE(chan);
2549                         return false;
2550                 }
2551
2552                 DLIST_ADD(back_channels, chan);
2553
2554                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2555                                    receive_notify2_message_list);
2556         }
2557
2558         if (chan->cli_pipe == NULL ||
2559             chan->cli_pipe->binding_handle == NULL) {
2560                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2561                         "NULL %s for printer %s\n",
2562                         chan->cli_pipe == NULL ?
2563                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2564                         printer));
2565                 return false;
2566         }
2567
2568         /*
2569          * Tell the specific printing tdb we want messages for this printer
2570          * by registering our PID.
2571          */
2572
2573         if (!print_notify_register_pid(snum)) {
2574                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2575                           printer));
2576         }
2577
2578         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2579                                                  talloc_tos(),
2580                                                  printer,
2581                                                  localprinter,
2582                                                  type,
2583                                                  0,
2584                                                  NULL,
2585                                                  handle,
2586                                                  &result);
2587         if (!NT_STATUS_IS_OK(status)) {
2588                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2589                 result = ntstatus_to_werror(status);
2590         } else if (!W_ERROR_IS_OK(result)) {
2591                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2592         }
2593
2594         chan->active_connections++;
2595         *_chan = chan;
2596
2597         return (W_ERROR_IS_OK(result));
2598 }
2599
2600 /****************************************************************
2601  ****************************************************************/
2602
2603 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2604                                                              const struct spoolss_NotifyOption *r)
2605 {
2606         struct spoolss_NotifyOption *option;
2607         uint32_t i,k;
2608
2609         if (!r) {
2610                 return NULL;
2611         }
2612
2613         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2614         if (!option) {
2615                 return NULL;
2616         }
2617
2618         *option = *r;
2619
2620         if (!option->count) {
2621                 return option;
2622         }
2623
2624         option->types = talloc_zero_array(option,
2625                 struct spoolss_NotifyOptionType, option->count);
2626         if (!option->types) {
2627                 talloc_free(option);
2628                 return NULL;
2629         }
2630
2631         for (i=0; i < option->count; i++) {
2632                 option->types[i] = r->types[i];
2633
2634                 if (option->types[i].count) {
2635                         option->types[i].fields = talloc_zero_array(option,
2636                                 union spoolss_Field, option->types[i].count);
2637                         if (!option->types[i].fields) {
2638                                 talloc_free(option);
2639                                 return NULL;
2640                         }
2641                         for (k=0; k<option->types[i].count; k++) {
2642                                 option->types[i].fields[k] =
2643                                         r->types[i].fields[k];
2644                         }
2645                 }
2646         }
2647
2648         return option;
2649 }
2650
2651 /****************************************************************
2652  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2653  *
2654  * before replying OK: status=0 a rpc call is made to the workstation
2655  * asking ReplyOpenPrinter
2656  *
2657  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2658  * called from api_spoolss_rffpcnex
2659 ****************************************************************/
2660
2661 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2662                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2663 {
2664         int snum = -1;
2665         struct spoolss_NotifyOption *option = r->in.notify_options;
2666         struct sockaddr_storage client_ss;
2667         ssize_t client_len;
2668
2669         /* store the notify value in the printer struct */
2670
2671         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2672
2673         if (!Printer) {
2674                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2675                         "Invalid handle (%s:%u:%u).\n",
2676                         OUR_HANDLE(r->in.handle)));
2677                 return WERR_BADFID;
2678         }
2679
2680         Printer->notify.flags           = r->in.flags;
2681         Printer->notify.options         = r->in.options;
2682         Printer->notify.printerlocal    = r->in.printer_local;
2683         Printer->notify.msg_ctx         = p->msg_ctx;
2684
2685         TALLOC_FREE(Printer->notify.option);
2686         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2687
2688         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2689
2690         /* Connect to the client machine and send a ReplyOpenPrinter */
2691
2692         if ( Printer->printer_type == SPLHND_SERVER)
2693                 snum = -1;
2694         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2695                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2696                 return WERR_BADFID;
2697
2698         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2699                   "remote_address is %s\n",
2700                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2701
2702         if (!lp_print_notify_backchannel(snum)) {
2703                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2704                         "backchannel disabled\n"));
2705                 return WERR_SERVER_UNAVAILABLE;
2706         }
2707
2708         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2709                                                   (struct sockaddr *) &client_ss,
2710                                                   sizeof(struct sockaddr_storage));
2711         if (client_len < 0) {
2712                 return WERR_NOMEM;
2713         }
2714
2715         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2716                                         Printer->notify.printerlocal, REG_SZ,
2717                                         &Printer->notify.cli_hnd,
2718                                         &Printer->notify.cli_chan,
2719                                         &client_ss, p->msg_ctx)) {
2720                 return WERR_SERVER_UNAVAILABLE;
2721         }
2722
2723         return WERR_OK;
2724 }
2725
2726 /*******************************************************************
2727  * fill a notify_info_data with the servername
2728  ********************************************************************/
2729
2730 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2731                                        int snum,
2732                                        struct spoolss_Notify *data,
2733                                        print_queue_struct *queue,
2734                                        struct spoolss_PrinterInfo2 *pinfo2,
2735                                        TALLOC_CTX *mem_ctx)
2736 {
2737         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2738 }
2739
2740 /*******************************************************************
2741  * fill a notify_info_data with the printername (not including the servername).
2742  ********************************************************************/
2743
2744 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2745                                         int snum,
2746                                         struct spoolss_Notify *data,
2747                                         print_queue_struct *queue,
2748                                         struct spoolss_PrinterInfo2 *pinfo2,
2749                                         TALLOC_CTX *mem_ctx)
2750 {
2751         /* the notify name should not contain the \\server\ part */
2752         const char *p = strrchr(pinfo2->printername, '\\');
2753
2754         if (!p) {
2755                 p = pinfo2->printername;
2756         } else {
2757                 p++;
2758         }
2759
2760         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2761 }
2762
2763 /*******************************************************************
2764  * fill a notify_info_data with the servicename
2765  ********************************************************************/
2766
2767 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2768                                       int snum,
2769                                       struct spoolss_Notify *data,
2770                                       print_queue_struct *queue,
2771                                       struct spoolss_PrinterInfo2 *pinfo2,
2772                                       TALLOC_CTX *mem_ctx)
2773 {
2774         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2775 }
2776
2777 /*******************************************************************
2778  * fill a notify_info_data with the port name
2779  ********************************************************************/
2780
2781 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2782                                      int snum,
2783                                      struct spoolss_Notify *data,
2784                                      print_queue_struct *queue,
2785                                      struct spoolss_PrinterInfo2 *pinfo2,
2786                                      TALLOC_CTX *mem_ctx)
2787 {
2788         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2789 }
2790
2791 /*******************************************************************
2792  * fill a notify_info_data with the printername
2793  * but it doesn't exist, have to see what to do
2794  ********************************************************************/
2795
2796 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2797                                        int snum,
2798                                        struct spoolss_Notify *data,
2799                                        print_queue_struct *queue,
2800                                        struct spoolss_PrinterInfo2 *pinfo2,
2801                                        TALLOC_CTX *mem_ctx)
2802 {
2803         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2804 }
2805
2806 /*******************************************************************
2807  * fill a notify_info_data with the comment
2808  ********************************************************************/
2809
2810 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2811                                    int snum,
2812                                    struct spoolss_Notify *data,
2813                                    print_queue_struct *queue,
2814                                    struct spoolss_PrinterInfo2 *pinfo2,
2815                                    TALLOC_CTX *mem_ctx)
2816 {
2817         const char *p;
2818
2819         if (*pinfo2->comment == '\0') {
2820                 p = lp_comment(talloc_tos(), snum);
2821         } else {
2822                 p = pinfo2->comment;
2823         }
2824
2825         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2826 }
2827
2828 /*******************************************************************
2829  * fill a notify_info_data with the comment
2830  * location = "Room 1, floor 2, building 3"
2831  ********************************************************************/
2832
2833 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2834                                     int snum,
2835                                     struct spoolss_Notify *data,
2836                                     print_queue_struct *queue,
2837                                     struct spoolss_PrinterInfo2 *pinfo2,
2838                                     TALLOC_CTX *mem_ctx)
2839 {
2840         const char *loc = pinfo2->location;
2841         NTSTATUS status;
2842
2843         status = printer_list_get_printer(mem_ctx,
2844                                           pinfo2->sharename,
2845                                           NULL,
2846                                           &loc,
2847                                           NULL);
2848         if (NT_STATUS_IS_OK(status)) {
2849                 if (loc == NULL) {
2850                         loc = pinfo2->location;
2851                 }
2852         }
2853
2854         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2855 }
2856
2857 /*******************************************************************
2858  * fill a notify_info_data with the device mode
2859  * jfm:xxxx don't to it for know but that's a real problem !!!
2860  ********************************************************************/
2861
2862 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2863                                    int snum,
2864                                    struct spoolss_Notify *data,
2865                                    print_queue_struct *queue,
2866                                    struct spoolss_PrinterInfo2 *pinfo2,
2867                                    TALLOC_CTX *mem_ctx)
2868 {
2869         /* for a dummy implementation we have to zero the fields */
2870         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2871 }
2872
2873 /*******************************************************************
2874  * fill a notify_info_data with the separator file name
2875  ********************************************************************/
2876
2877 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2878                                    int snum,
2879                                    struct spoolss_Notify *data,
2880                                    print_queue_struct *queue,
2881                                    struct spoolss_PrinterInfo2 *pinfo2,
2882                                    TALLOC_CTX *mem_ctx)
2883 {
2884         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2885 }
2886
2887 /*******************************************************************
2888  * fill a notify_info_data with the print processor
2889  * jfm:xxxx return always winprint to indicate we don't do anything to it
2890  ********************************************************************/
2891
2892 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2893                                            int snum,
2894                                            struct spoolss_Notify *data,
2895                                            print_queue_struct *queue,
2896                                            struct spoolss_PrinterInfo2 *pinfo2,
2897                                            TALLOC_CTX *mem_ctx)
2898 {
2899         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2900 }
2901
2902 /*******************************************************************
2903  * fill a notify_info_data with the print processor options
2904  * jfm:xxxx send an empty string
2905  ********************************************************************/
2906
2907 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2908                                       int snum,
2909                                       struct spoolss_Notify *data,
2910                                       print_queue_struct *queue,
2911                                       struct spoolss_PrinterInfo2 *pinfo2,
2912                                       TALLOC_CTX *mem_ctx)
2913 {
2914         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2915 }
2916
2917 /*******************************************************************
2918  * fill a notify_info_data with the data type
2919  * jfm:xxxx always send RAW as data type
2920  ********************************************************************/
2921
2922 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2923                                     int snum,
2924                                     struct spoolss_Notify *data,
2925                                     print_queue_struct *queue,
2926                                     struct spoolss_PrinterInfo2 *pinfo2,
2927                                     TALLOC_CTX *mem_ctx)
2928 {
2929         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2930 }
2931
2932 /*******************************************************************
2933  * fill a notify_info_data with the security descriptor
2934  * jfm:xxxx send an null pointer to say no security desc
2935  * have to implement security before !
2936  ********************************************************************/
2937
2938 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2939                                          int snum,
2940                                          struct spoolss_Notify *data,
2941                                          print_queue_struct *queue,
2942                                          struct spoolss_PrinterInfo2 *pinfo2,
2943                                          TALLOC_CTX *mem_ctx)
2944 {
2945         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2946 }
2947
2948 /*******************************************************************
2949  * fill a notify_info_data with the attributes
2950  * jfm:xxxx a samba printer is always shared
2951  ********************************************************************/
2952
2953 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2954                                       int snum,
2955                                       struct spoolss_Notify *data,
2956                                       print_queue_struct *queue,
2957                                       struct spoolss_PrinterInfo2 *pinfo2,
2958                                       TALLOC_CTX *mem_ctx)
2959 {
2960         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2961 }
2962
2963 /*******************************************************************
2964  * fill a notify_info_data with the priority
2965  ********************************************************************/
2966
2967 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2968                                     int snum,
2969                                     struct spoolss_Notify *data,
2970                                     print_queue_struct *queue,
2971                                     struct spoolss_PrinterInfo2 *pinfo2,
2972                                     TALLOC_CTX *mem_ctx)
2973 {
2974         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2975 }
2976
2977 /*******************************************************************
2978  * fill a notify_info_data with the default priority
2979  ********************************************************************/
2980
2981 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2982                                             int snum,
2983                                             struct spoolss_Notify *data,
2984                                             print_queue_struct *queue,
2985                                             struct spoolss_PrinterInfo2 *pinfo2,
2986                                             TALLOC_CTX *mem_ctx)
2987 {
2988         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2989 }
2990
2991 /*******************************************************************
2992  * fill a notify_info_data with the start time
2993  ********************************************************************/
2994
2995 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2996                                       int snum,
2997                                       struct spoolss_Notify *data,
2998                                       print_queue_struct *queue,
2999                                       struct spoolss_PrinterInfo2 *pinfo2,
3000                                       TALLOC_CTX *mem_ctx)
3001 {
3002         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3003 }
3004
3005 /*******************************************************************
3006  * fill a notify_info_data with the until time
3007  ********************************************************************/
3008
3009 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3010                                       int snum,
3011                                       struct spoolss_Notify *data,
3012                                       print_queue_struct *queue,
3013                                       struct spoolss_PrinterInfo2 *pinfo2,
3014                                       TALLOC_CTX *mem_ctx)
3015 {
3016         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3017 }
3018
3019 /*******************************************************************
3020  * fill a notify_info_data with the status
3021  ********************************************************************/
3022
3023 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3024                                   int snum,
3025                                   struct spoolss_Notify *data,
3026                                   print_queue_struct *queue,
3027                                   struct spoolss_PrinterInfo2 *pinfo2,
3028                                   TALLOC_CTX *mem_ctx)
3029 {
3030         print_status_struct status;
3031
3032         print_queue_length(msg_ctx, snum, &status);
3033         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3034 }
3035
3036 /*******************************************************************
3037  * fill a notify_info_data with the number of jobs queued
3038  ********************************************************************/
3039
3040 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3041                                  int snum,
3042                                  struct spoolss_Notify *data,
3043                                  print_queue_struct *queue,
3044                                  struct spoolss_PrinterInfo2 *pinfo2,
3045                                  TALLOC_CTX *mem_ctx)
3046 {
3047         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3048                 data, print_queue_length(msg_ctx, snum, NULL));
3049 }
3050
3051 /*******************************************************************
3052  * fill a notify_info_data with the average ppm
3053  ********************************************************************/
3054
3055 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3056                                        int snum,
3057                                        struct spoolss_Notify *data,
3058                                        print_queue_struct *queue,
3059                                        struct spoolss_PrinterInfo2 *pinfo2,
3060                                        TALLOC_CTX *mem_ctx)
3061 {
3062         /* always respond 8 pages per minutes */
3063         /* a little hard ! */
3064         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3065 }
3066
3067 /*******************************************************************
3068  * fill a notify_info_data with username
3069  ********************************************************************/
3070
3071 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3072                                     int snum,
3073                                     struct spoolss_Notify *data,
3074                                     print_queue_struct *queue,
3075                                     struct spoolss_PrinterInfo2 *pinfo2,
3076                                     TALLOC_CTX *mem_ctx)
3077 {
3078         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3079 }
3080
3081 /*******************************************************************
3082  * fill a notify_info_data with job status
3083  ********************************************************************/
3084
3085 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3086                                       int snum,
3087                                       struct spoolss_Notify *data,
3088                                       print_queue_struct *queue,
3089                                       struct spoolss_PrinterInfo2 *pinfo2,
3090                                       TALLOC_CTX *mem_ctx)
3091 {
3092         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3093 }
3094
3095 /*******************************************************************
3096  * fill a notify_info_data with job name
3097  ********************************************************************/
3098
3099 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3100                                     int snum,
3101                                     struct spoolss_Notify *data,
3102                                     print_queue_struct *queue,
3103                                     struct spoolss_PrinterInfo2 *pinfo2,
3104                                     TALLOC_CTX *mem_ctx)
3105 {
3106         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3107 }
3108
3109 /*******************************************************************
3110  * fill a notify_info_data with job status
3111  ********************************************************************/
3112
3113 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3114                                              int snum,
3115                                              struct spoolss_Notify *data,
3116                                              print_queue_struct *queue,
3117                                              struct spoolss_PrinterInfo2 *pinfo2,
3118                                              TALLOC_CTX *mem_ctx)
3119 {
3120         /*
3121          * Now we're returning job status codes we just return a "" here. JRA.
3122          */
3123
3124         const char *p = "";
3125
3126 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3127         p = "unknown";
3128
3129         switch (queue->status) {
3130         case LPQ_QUEUED:
3131                 p = "Queued";
3132                 break;
3133         case LPQ_PAUSED:
3134                 p = "";    /* NT provides the paused string */
3135                 break;
3136         case LPQ_SPOOLING:
3137                 p = "Spooling";
3138                 break;
3139         case LPQ_PRINTING:
3140                 p = "Printing";
3141                 break;
3142         }
3143 #endif /* NO LONGER NEEDED. */
3144
3145         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3146 }
3147
3148 /*******************************************************************
3149  * fill a notify_info_data with job time
3150  ********************************************************************/
3151
3152 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3153                                     int snum,
3154                                     struct spoolss_Notify *data,
3155                                     print_queue_struct *queue,
3156                                     struct spoolss_PrinterInfo2 *pinfo2,
3157                                     TALLOC_CTX *mem_ctx)
3158 {
3159         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3160 }
3161
3162 /*******************************************************************
3163  * fill a notify_info_data with job size
3164  ********************************************************************/
3165
3166 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3167                                     int snum,
3168                                     struct spoolss_Notify *data,
3169                                     print_queue_struct *queue,
3170                                     struct spoolss_PrinterInfo2 *pinfo2,
3171                                     TALLOC_CTX *mem_ctx)
3172 {
3173         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3174 }
3175
3176 /*******************************************************************
3177  * fill a notify_info_data with page info
3178  ********************************************************************/
3179 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3180                                        int snum,
3181                                 struct spoolss_Notify *data,
3182                                 print_queue_struct *queue,
3183                                 struct spoolss_PrinterInfo2 *pinfo2,
3184                                 TALLOC_CTX *mem_ctx)
3185 {
3186         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3187 }
3188
3189 /*******************************************************************
3190  * fill a notify_info_data with pages printed info.
3191  ********************************************************************/
3192 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3193                                          int snum,
3194                                 struct spoolss_Notify *data,
3195                                 print_queue_struct *queue,
3196                                 struct spoolss_PrinterInfo2 *pinfo2,
3197                                 TALLOC_CTX *mem_ctx)
3198 {
3199         /* Add code when back-end tracks this */
3200         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3201 }
3202
3203 /*******************************************************************
3204  Fill a notify_info_data with job position.
3205  ********************************************************************/
3206
3207 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3208                                         int snum,
3209                                         struct spoolss_Notify *data,
3210                                         print_queue_struct *queue,
3211                                         struct spoolss_PrinterInfo2 *pinfo2,
3212                                         TALLOC_CTX *mem_ctx)
3213 {
3214         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3215 }
3216
3217 /*******************************************************************
3218  Fill a notify_info_data with submitted time.
3219  ********************************************************************/
3220
3221 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3222                                           int snum,
3223                                           struct spoolss_Notify *data,
3224                                           print_queue_struct *queue,
3225                                           struct spoolss_PrinterInfo2 *pinfo2,
3226                                           TALLOC_CTX *mem_ctx)
3227 {
3228         data->data.string.string = NULL;
3229         data->data.string.size = 0;
3230
3231         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3232                                &data->data.string.string,
3233                                &data->data.string.size);
3234
3235 }
3236
3237 struct s_notify_info_data_table
3238 {
3239         enum spoolss_NotifyType type;
3240         uint16_t field;
3241         const char *name;
3242         enum spoolss_NotifyTable variable_type;
3243         void (*fn) (struct messaging_context *msg_ctx,
3244                     int snum, struct spoolss_Notify *data,
3245                     print_queue_struct *queue,
3246                     struct spoolss_PrinterInfo2 *pinfo2,
3247                     TALLOC_CTX *mem_ctx);
3248 };
3249
3250 /* A table describing the various print notification constants and
3251    whether the notification data is a pointer to a variable sized
3252    buffer, a one value uint32_t or a two value uint32_t. */
3253
3254 static const struct s_notify_info_data_table notify_info_data_table[] =
3255 {
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3282 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3283 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3284 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3285 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3286 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3287 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3288 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3289 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3290 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3291 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3292 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3293 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3294 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3295 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3296 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3301 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3302 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3304 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3305 };
3306
3307 /*******************************************************************
3308  Return the variable_type of info_data structure.
3309 ********************************************************************/
3310
3311 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3312                                                                   uint16_t field)
3313 {
3314         int i=0;
3315
3316         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3317                 if ( (notify_info_data_table[i].type == type) &&
3318                      (notify_info_data_table[i].field == field) ) {
3319                         return notify_info_data_table[i].variable_type;
3320                 }
3321         }
3322
3323         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3324
3325         return (enum spoolss_NotifyTable) 0;
3326 }
3327
3328 /****************************************************************************
3329 ****************************************************************************/
3330
3331 static bool search_notify(enum spoolss_NotifyType type,
3332                           uint16_t field,
3333                           int *value)
3334 {
3335         int i;
3336
3337         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3338                 if (notify_info_data_table[i].type == type &&
3339                     notify_info_data_table[i].field == field &&
3340                     notify_info_data_table[i].fn != NULL) {
3341                         *value = i;
3342                         return true;
3343                 }
3344         }
3345
3346         return false;
3347 }
3348
3349 /****************************************************************************
3350 ****************************************************************************/
3351
3352 static void construct_info_data(struct spoolss_Notify *info_data,
3353                                 enum spoolss_NotifyType type,
3354                                 uint16_t field, int id)
3355 {
3356         info_data->type                 = type;
3357         info_data->field.field          = field;
3358         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3359         info_data->job_id               = id;
3360 }
3361
3362 /*******************************************************************
3363  *
3364  * fill a notify_info struct with info asked
3365  *
3366  ********************************************************************/
3367
3368 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3369                                           struct printer_handle *print_hnd,
3370                                           struct spoolss_NotifyInfo *info,
3371                                           struct spoolss_PrinterInfo2 *pinfo2,
3372                                           int snum,
3373                                           const struct spoolss_NotifyOptionType *option_type,
3374                                           uint32_t id,
3375                                           TALLOC_CTX *mem_ctx)
3376 {
3377         int field_num,j;
3378         enum spoolss_NotifyType type;
3379         uint16_t field;
3380
3381         struct spoolss_Notify *current_data;
3382
3383         type = option_type->type;
3384
3385         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3386                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3387                 option_type->count, lp_servicename(talloc_tos(), snum)));
3388
3389         for(field_num=0; field_num < option_type->count; field_num++) {
3390                 field = option_type->fields[field_num].field;
3391
3392                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3393
3394                 if (!search_notify(type, field, &j) )
3395                         continue;
3396
3397                 info->notifies = talloc_realloc(info, info->notifies,
3398                                                       struct spoolss_Notify,
3399                                                       info->count + 1);
3400                 if (info->notifies == NULL) {
3401                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3402                         return false;
3403                 }
3404
3405                 current_data = &info->notifies[info->count];
3406
3407                 construct_info_data(current_data, type, field, id);
3408
3409                 DEBUG(10, ("construct_notify_printer_info: "
3410                            "calling [%s]  snum=%d  printername=[%s])\n",
3411                            notify_info_data_table[j].name, snum,
3412                            pinfo2->printername));
3413
3414                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3415                                              NULL, pinfo2, mem_ctx);
3416
3417                 info->count++;
3418         }
3419
3420         return true;
3421 }
3422
3423 /*******************************************************************
3424  *
3425  * fill a notify_info struct with info asked
3426  *
3427  ********************************************************************/
3428
3429 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3430                                        print_queue_struct *queue,
3431                                        struct spoolss_NotifyInfo *info,
3432                                        struct spoolss_PrinterInfo2 *pinfo2,
3433                                        int snum,
3434                                        const struct spoolss_NotifyOptionType *option_type,
3435                                        uint32_t id,
3436                                        TALLOC_CTX *mem_ctx)
3437 {
3438         int field_num,j;
3439         enum spoolss_NotifyType type;
3440         uint16_t field;
3441         struct spoolss_Notify *current_data;
3442
3443         DEBUG(4,("construct_notify_jobs_info\n"));
3444
3445         type = option_type->type;
3446
3447         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3448                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3449                 option_type->count));
3450
3451         for(field_num=0; field_num<option_type->count; field_num++) {
3452                 field = option_type->fields[field_num].field;
3453
3454                 if (!search_notify(type, field, &j) )
3455                         continue;
3456
3457                 info->notifies = talloc_realloc(info, info->notifies,
3458                                                       struct spoolss_Notify,
3459                                                       info->count + 1);
3460                 if (info->notifies == NULL) {
3461                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3462                         return false;
3463                 }
3464
3465                 current_data=&(info->notifies[info->count]);
3466
3467                 construct_info_data(current_data, type, field, id);
3468                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3469                                              queue, pinfo2, mem_ctx);
3470                 info->count++;
3471         }
3472
3473         return true;
3474 }
3475
3476 /*
3477  * JFM: The enumeration is not that simple, it's even non obvious.
3478  *
3479  * let's take an example: I want to monitor the PRINTER SERVER for
3480  * the printer's name and the number of jobs currently queued.
3481  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3482  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3483  *
3484  * I have 3 printers on the back of my server.
3485  *
3486  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3487  * structures.
3488  *   Number     Data                    Id
3489  *      1       printer 1 name          1
3490  *      2       printer 1 cjob          1
3491  *      3       printer 2 name          2
3492  *      4       printer 2 cjob          2
3493  *      5       printer 3 name          3
3494  *      6       printer 3 name          3
3495  *
3496  * that's the print server case, the printer case is even worse.
3497  */
3498
3499 /*******************************************************************
3500  *
3501  * enumerate all printers on the printserver
3502  * fill a notify_info struct with info asked
3503  *
3504  ********************************************************************/
3505
3506 static WERROR printserver_notify_info(struct pipes_struct *p,
3507                                       struct policy_handle *hnd,
3508                                       struct spoolss_NotifyInfo *info,
3509                                       TALLOC_CTX *mem_ctx)
3510 {
3511         int snum;
3512         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3513         int n_services=lp_numservices();
3514         int i;
3515         struct spoolss_NotifyOption *option;
3516         struct spoolss_NotifyOptionType option_type;
3517         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3518         WERROR result;
3519
3520         DEBUG(4,("printserver_notify_info\n"));
3521
3522         if (!Printer)
3523                 return WERR_BADFID;
3524
3525         option = Printer->notify.option;
3526
3527         info->version   = 2;
3528         info->notifies  = NULL;
3529         info->count     = 0;
3530
3531         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3532            sending a ffpcn() request first */
3533
3534         if ( !option )
3535                 return WERR_BADFID;
3536
3537         for (i=0; i<option->count; i++) {
3538                 option_type = option->types[i];
3539
3540                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3541                         continue;
3542
3543                 for (snum = 0; snum < n_services; snum++) {
3544                         if (!lp_browseable(snum) ||
3545                             !lp_snum_ok(snum) ||
3546                             !lp_printable(snum)) {
3547                                 continue; /* skip */
3548                         }
3549
3550                         /* Maybe we should use the SYSTEM session_info here... */
3551                         result = winreg_get_printer_internal(mem_ctx,
3552                                                     get_session_info_system(),
3553                                                     p->msg_ctx,
3554                                                     lp_servicename(talloc_tos(), snum),
3555                                                     &pinfo2);
3556                         if (!W_ERROR_IS_OK(result)) {
3557                                 DEBUG(4, ("printserver_notify_info: "
3558                                           "Failed to get printer [%s]\n",
3559                                           lp_servicename(talloc_tos(), snum)));
3560                                 continue;
3561                         }
3562
3563
3564                         construct_notify_printer_info(p->msg_ctx,
3565                                                       Printer, info,
3566                                                       pinfo2, snum,
3567                                                       &option_type, snum,
3568                                                       mem_ctx);
3569
3570                         TALLOC_FREE(pinfo2);
3571                 }
3572         }
3573
3574 #if 0
3575         /*
3576          * Debugging information, don't delete.
3577          */
3578
3579         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3580         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3581         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3582
3583         for (i=0; i<info->count; i++) {
3584                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3585                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3586                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3587         }
3588 #endif
3589
3590         return WERR_OK;
3591 }
3592
3593 /*******************************************************************
3594  *
3595  * fill a notify_info struct with info asked
3596  *
3597  ********************************************************************/
3598
3599 static WERROR printer_notify_info(struct pipes_struct *p,
3600                                   struct policy_handle *hnd,
3601                                   struct spoolss_NotifyInfo *info,
3602                                   TALLOC_CTX *mem_ctx)
3603 {
3604         int snum;
3605         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3606         int i;
3607         uint32_t id;
3608         struct spoolss_NotifyOption *option;
3609         struct spoolss_NotifyOptionType option_type;
3610         int count,j;
3611         print_queue_struct *queue=NULL;
3612         print_status_struct status;
3613         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3614         WERROR result;
3615         struct tdb_print_db *pdb;
3616
3617         DEBUG(4,("printer_notify_info\n"));
3618
3619         if (!Printer)
3620                 return WERR_BADFID;
3621
3622         option = Printer->notify.option;
3623         id = 0x0;
3624
3625         info->version   = 2;
3626         info->notifies  = NULL;
3627         info->count     = 0;
3628
3629         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3630            sending a ffpcn() request first */
3631
3632         if ( !option )
3633                 return WERR_BADFID;
3634
3635         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3636                 return WERR_BADFID;
3637         }
3638
3639         pdb = get_print_db_byname(Printer->sharename);
3640         if (pdb == NULL) {
3641                 return WERR_BADFID;
3642         }
3643
3644         /* Maybe we should use the SYSTEM session_info here... */
3645         result = winreg_get_printer_internal(mem_ctx,
3646                                     get_session_info_system(),
3647                                     p->msg_ctx,
3648                                     lp_servicename(talloc_tos(), snum), &pinfo2);
3649         if (!W_ERROR_IS_OK(result)) {
3650                 result = WERR_BADFID;
3651                 goto err_pdb_drop;
3652         }
3653
3654         /*
3655          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3656          * correct servername.
3657          */
3658         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3659         if (pinfo2->servername == NULL) {
3660                 result = WERR_NOMEM;
3661                 goto err_pdb_drop;
3662         }
3663
3664         for (i = 0; i < option->count; i++) {
3665                 option_type = option->types[i];
3666
3667                 switch (option_type.type) {
3668                 case PRINTER_NOTIFY_TYPE:
3669                         if (construct_notify_printer_info(p->msg_ctx,
3670                                                           Printer, info,
3671                                                           pinfo2, snum,
3672                                                           &option_type, id,
3673                                                           mem_ctx)) {
3674                                 id--;
3675                         }
3676                         break;
3677
3678                 case JOB_NOTIFY_TYPE:
3679
3680                         count = print_queue_status(p->msg_ctx, snum, &queue,
3681                                                    &status);
3682
3683                         for (j = 0; j < count; j++) {
3684                                 uint32_t jobid;
3685                                 jobid = sysjob_to_jobid_pdb(pdb,
3686                                                             queue[j].sysjob);
3687                                 if (jobid == (uint32_t)-1) {
3688                                         DEBUG(2, ("ignoring untracked job %d\n",
3689                                                   queue[j].sysjob));
3690                                         continue;
3691                                 }
3692                                 /* FIXME check return value */
3693                                 construct_notify_jobs_info(p->msg_ctx,
3694                                                            &queue[j], info,
3695                                                            pinfo2, snum,
3696                                                            &option_type,
3697                                                            jobid,
3698                                                            mem_ctx);
3699                         }
3700
3701                         SAFE_FREE(queue);
3702                         break;
3703                 }
3704         }
3705
3706         /*
3707          * Debugging information, don't delete.
3708          */
3709         /*
3710         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3711         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3712         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3713
3714         for (i=0; i<info->count; i++) {
3715                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3716                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3717                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3718         }
3719         */
3720
3721         talloc_free(pinfo2);
3722         result = WERR_OK;
3723 err_pdb_drop:
3724         release_print_db(pdb);
3725         return result;
3726 }
3727
3728 /****************************************************************
3729  _spoolss_RouterRefreshPrinterChangeNotify
3730 ****************************************************************/
3731
3732 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3733                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3734 {
3735         struct spoolss_NotifyInfo *info;
3736
3737         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3738         WERROR result = WERR_BADFID;
3739
3740         /* we always have a spoolss_NotifyInfo struct */
3741         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3742         if (!info) {
3743                 result = WERR_NOMEM;
3744                 goto done;
3745         }
3746
3747         *r->out.info = info;
3748
3749         if (!Printer) {
3750                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3751                         "Invalid handle (%s:%u:%u).\n",
3752                         OUR_HANDLE(r->in.handle)));
3753                 goto done;
3754         }
3755
3756         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3757
3758         /*
3759          *      We are now using the change value, and
3760          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3761          *      I don't have a global notification system, I'm sending back all the
3762          *      information even when _NOTHING_ has changed.
3763          */
3764
3765         /* We need to keep track of the change value to send back in
3766            RRPCN replies otherwise our updates are ignored. */
3767
3768         Printer->notify.fnpcn = true;
3769
3770         if (Printer->notify.cli_chan != NULL &&
3771             Printer->notify.cli_chan->active_connections > 0) {
3772                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3773                         "Saving change value in request [%x]\n",
3774                         r->in.change_low));
3775                 Printer->notify.change = r->in.change_low;
3776         }
3777
3778         /* just ignore the spoolss_NotifyOption */
3779
3780         switch (Printer->printer_type) {
3781                 case SPLHND_SERVER:
3782                         result = printserver_notify_info(p, r->in.handle,
3783                                                          info, p->mem_ctx);
3784                         break;
3785
3786                 case SPLHND_PRINTER:
3787                         result = printer_notify_info(p, r->in.handle,
3788                                                      info, p->mem_ctx);
3789                         break;
3790         }
3791
3792         Printer->notify.fnpcn = false;
3793
3794 done:
3795         return result;
3796 }
3797
3798 /********************************************************************
3799  ********************************************************************/
3800
3801 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3802                                  const char *servername,
3803                                  const char *printername,
3804                                  const char **printername_p)
3805 {
3806         /* FIXME: add lp_force_printername() */
3807
3808         if (servername == NULL) {
3809                 *printername_p = talloc_strdup(mem_ctx, printername);
3810                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3811                 return WERR_OK;
3812         }
3813
3814         if (servername[0] == '\\' && servername[1] == '\\') {
3815                 servername += 2;
3816         }
3817
3818         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3819         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3820
3821         return WERR_OK;
3822 }
3823
3824 /********************************************************************
3825  ********************************************************************/
3826
3827 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3828                                           const char *printername)
3829 {
3830         if (dm == NULL) {
3831                 return;
3832         }
3833
3834         dm->devicename = talloc_strndup(dm, printername,
3835                                         MIN(strlen(printername), 31));
3836 }
3837
3838 /********************************************************************
3839  * construct_printer_info_0
3840  * fill a printer_info_0 struct
3841  ********************************************************************/
3842
3843 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3844                                       const struct auth_session_info *session_info,
3845                                       struct messaging_context *msg_ctx,
3846                                       struct spoolss_PrinterInfo2 *info2,
3847                                       const char *servername,
3848                                       struct spoolss_PrinterInfo0 *r,
3849                                       int snum)
3850 {
3851         int count;
3852         struct printer_session_counter *session_counter;
3853         struct timeval setuptime;
3854         print_status_struct status;
3855         WERROR result;
3856
3857         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3858         if (!W_ERROR_IS_OK(result)) {
3859                 return result;
3860         }
3861
3862         if (servername) {
3863                 r->servername = talloc_strdup(mem_ctx, servername);
3864                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3865         } else {
3866                 r->servername = NULL;
3867         }
3868
3869         count = print_queue_length(msg_ctx, snum, &status);
3870
3871         /* check if we already have a counter for this printer */
3872         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3873                 if (session_counter->snum == snum)
3874                         break;
3875         }
3876
3877         /* it's the first time, add it to the list */
3878         if (session_counter == NULL) {
3879                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3880                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3881                 session_counter->snum           = snum;
3882                 session_counter->counter        = 0;
3883                 DLIST_ADD(counter_list, session_counter);
3884         }
3885
3886         /* increment it */
3887         session_counter->counter++;
3888
3889         r->cjobs                        = count;
3890         r->total_jobs                   = 0;
3891         r->total_bytes                  = 0;
3892
3893         get_startup_time(&setuptime);
3894         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3895
3896         /* JFM:
3897          * the global_counter should be stored in a TDB as it's common to all the clients
3898          * and should be zeroed on samba startup
3899          */
3900         r->global_counter               = session_counter->counter;
3901         r->total_pages                  = 0;
3902         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3903         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3904         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3905         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3906         r->spooling                     = 0;
3907         r->max_spooling                 = 0;
3908         r->session_counter              = session_counter->counter;
3909         r->num_error_out_of_paper       = 0x0;
3910         r->num_error_not_ready          = 0x0;          /* number of print failure */
3911         r->job_error                    = 0x0;
3912         r->number_of_processors         = 0x1;
3913         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3914         r->high_part_total_bytes        = 0x0;
3915
3916         /* ChangeID in milliseconds*/
3917         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3918                                     info2->sharename, &r->change_id);
3919
3920         r->last_error                   = WERR_OK;
3921         r->status                       = nt_printq_status(status.status);
3922         r->enumerate_network_printers   = 0x0;
3923         r->c_setprinter                 = 0x0;
3924         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3925         r->processor_level              = 0x6;          /* 6  ???*/
3926         r->ref_ic                       = 0;
3927         r->reserved2                    = 0;
3928         r->reserved3                    = 0;
3929
3930         return WERR_OK;
3931 }
3932
3933
3934 /********************************************************************
3935  * construct_printer_info1
3936  * fill a spoolss_PrinterInfo1 struct
3937 ********************************************************************/
3938
3939 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3940                                       const struct spoolss_PrinterInfo2 *info2,
3941                                       uint32_t flags,
3942                                       const char *servername,
3943                                       struct spoolss_PrinterInfo1 *r,
3944                                       int snum)
3945 {
3946         WERROR result;
3947
3948         r->flags                = flags;
3949
3950         if (info2->comment == NULL || info2->comment[0] == '\0') {
3951                 r->comment      = lp_comment(mem_ctx, snum);
3952         } else {
3953                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3954         }
3955         W_ERROR_HAVE_NO_MEMORY(r->comment);
3956
3957         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3958         if (!W_ERROR_IS_OK(result)) {
3959                 return result;
3960         }
3961
3962         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3963                                                   r->name,
3964                                                   info2->drivername,
3965                                                   r->comment);
3966         W_ERROR_HAVE_NO_MEMORY(r->description);
3967
3968         return WERR_OK;
3969 }
3970
3971 /********************************************************************
3972  * construct_printer_info2
3973  * fill a spoolss_PrinterInfo2 struct
3974 ********************************************************************/
3975
3976 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3977                                       struct messaging_context *msg_ctx,
3978                                       const struct spoolss_PrinterInfo2 *info2,
3979                                       const char *servername,
3980                                       struct spoolss_PrinterInfo2 *r,
3981                                       int snum)
3982 {
3983         int count;
3984         print_status_struct status;
3985         WERROR result;
3986
3987         count = print_queue_length(msg_ctx, snum, &status);
3988
3989         if (servername) {
3990                 r->servername           = talloc_strdup(mem_ctx, servername);
3991                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3992         } else {
3993                 r->servername           = NULL;
3994         }
3995
3996         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3997         if (!W_ERROR_IS_OK(result)) {
3998                 return result;
3999         }
4000
4001         r->sharename            = lp_servicename(mem_ctx, snum);
4002         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4003         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4004         W_ERROR_HAVE_NO_MEMORY(r->portname);
4005         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4006         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4007
4008         if (info2->comment[0] == '\0') {
4009                 r->comment      = lp_comment(mem_ctx, snum);
4010         } else {
4011                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4012         }
4013         W_ERROR_HAVE_NO_MEMORY(r->comment);
4014
4015         r->location     = talloc_strdup(mem_ctx, info2->location);
4016         if (info2->location[0] == '\0') {
4017                 const char *loc = NULL;
4018                 NTSTATUS nt_status;
4019
4020                 nt_status = printer_list_get_printer(mem_ctx,
4021                                                      info2->sharename,
4022                                                      NULL,
4023                                                      &loc,
4024                                                      NULL);
4025                 if (NT_STATUS_IS_OK(nt_status)) {
4026                         if (loc != NULL) {
4027                                 r->location = talloc_strdup(mem_ctx, loc);
4028                         }
4029                 }
4030         }
4031         W_ERROR_HAVE_NO_MEMORY(r->location);
4032
4033         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4034         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4035         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4036         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4037         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4038         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4039         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4040         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4041
4042         r->attributes           = info2->attributes;
4043
4044         r->priority             = info2->priority;
4045         r->defaultpriority      = info2->defaultpriority;
4046         r->starttime            = info2->starttime;
4047         r->untiltime            = info2->untiltime;
4048         r->status               = nt_printq_status(status.status);
4049         r->cjobs                = count;
4050         r->averageppm           = info2->averageppm;
4051
4052         if (info2->devmode != NULL) {
4053                 result = copy_devicemode(mem_ctx,
4054                                          info2->devmode,
4055                                          &r->devmode);
4056                 if (!W_ERROR_IS_OK(result)) {
4057                         return result;
4058                 }
4059         } else if (lp_default_devmode(snum)) {
4060                 result = spoolss_create_default_devmode(mem_ctx,
4061                                                         info2->printername,
4062                                                         &r->devmode);
4063                 if (!W_ERROR_IS_OK(result)) {
4064                         return result;
4065                 }
4066         } else {
4067                 r->devmode = NULL;
4068                 DEBUG(8,("Returning NULL Devicemode!\n"));
4069         }
4070
4071         compose_devicemode_devicename(r->devmode, r->printername);
4072
4073         r->secdesc = NULL;
4074
4075         if (info2->secdesc != NULL) {
4076                 /* don't use talloc_steal() here unless you do a deep steal of all
4077                    the SEC_DESC members */
4078
4079                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4080         }
4081
4082         return WERR_OK;
4083 }
4084
4085 /********************************************************************
4086  * construct_printer_info3
4087  * fill a spoolss_PrinterInfo3 struct
4088  ********************************************************************/
4089
4090 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4091                                       const struct spoolss_PrinterInfo2 *info2,
4092                                       const char *servername,
4093                                       struct spoolss_PrinterInfo3 *r,
4094                                       int snum)
4095 {
4096         /* These are the components of the SD we are returning. */
4097
4098         if (info2->secdesc != NULL) {
4099                 /* don't use talloc_steal() here unless you do a deep steal of all
4100                    the SEC_DESC members */
4101
4102                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4103                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4104         }
4105
4106         return WERR_OK;
4107 }
4108
4109 /********************************************************************
4110  * construct_printer_info4
4111  * fill a spoolss_PrinterInfo4 struct
4112  ********************************************************************/
4113
4114 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4115                                       const struct spoolss_PrinterInfo2 *info2,
4116                                       const char *servername,
4117                                       struct spoolss_PrinterInfo4 *r,
4118                                       int snum)
4119 {
4120         WERROR result;
4121
4122         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4123         if (!W_ERROR_IS_OK(result)) {
4124                 return result;
4125         }
4126
4127         if (servername) {
4128                 r->servername   = talloc_strdup(mem_ctx, servername);
4129                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4130         } else {
4131                 r->servername = NULL;
4132         }
4133
4134         r->attributes   = info2->attributes;
4135
4136         return WERR_OK;
4137 }
4138
4139 /********************************************************************
4140  * construct_printer_info5
4141  * fill a spoolss_PrinterInfo5 struct
4142  ********************************************************************/
4143
4144 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4145                                       const struct spoolss_PrinterInfo2 *info2,
4146                                       const char *servername,
4147                                       struct spoolss_PrinterInfo5 *r,
4148                                       int snum)
4149 {
4150         WERROR result;
4151
4152         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4153         if (!W_ERROR_IS_OK(result)) {
4154                 return result;
4155         }
4156
4157         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4158         W_ERROR_HAVE_NO_MEMORY(r->portname);
4159
4160         r->attributes   = info2->attributes;
4161
4162         /* these two are not used by NT+ according to MSDN */
4163         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4164         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4165
4166         return WERR_OK;
4167 }
4168
4169 /********************************************************************
4170  * construct_printer_info_6
4171  * fill a spoolss_PrinterInfo6 struct
4172  ********************************************************************/
4173
4174 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4175                                       struct messaging_context *msg_ctx,
4176                                       const struct spoolss_PrinterInfo2 *info2,
4177                                       const char *servername,
4178                                       struct spoolss_PrinterInfo6 *r,
4179                                       int snum)
4180 {
4181         print_status_struct status;
4182
4183         print_queue_length(msg_ctx, snum, &status);
4184
4185         r->status = nt_printq_status(status.status);
4186
4187         return WERR_OK;
4188 }
4189
4190 /********************************************************************
4191  * construct_printer_info7
4192  * fill a spoolss_PrinterInfo7 struct
4193  ********************************************************************/
4194
4195 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4196                                       struct messaging_context *msg_ctx,
4197                                       const char *servername,
4198                                       struct spoolss_PrinterInfo7 *r,
4199                                       int snum)
4200 {
4201         const struct auth_session_info *session_info;
4202         char *printer;
4203         WERROR werr;
4204         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4205         if (tmp_ctx == NULL) {
4206                 return WERR_NOMEM;
4207         }
4208
4209         session_info = get_session_info_system();
4210         SMB_ASSERT(session_info != NULL);
4211
4212         printer = lp_servicename(tmp_ctx, snum);
4213         if (printer == NULL) {
4214                 DEBUG(0, ("invalid printer snum %d\n", snum));
4215                 werr = WERR_INVALID_PARAM;
4216                 goto out_tmp_free;
4217         }
4218
4219         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4220                                  servername, printer, NULL)) {
4221                 struct GUID guid;
4222                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4223                                            printer, &guid);
4224                 if (!W_ERROR_IS_OK(werr)) {
4225                         goto out_tmp_free;
4226                 }
4227                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4228                 r->action = DSPRINT_PUBLISH;
4229         } else {
4230                 r->guid = talloc_strdup(mem_ctx, "");
4231                 r->action = DSPRINT_UNPUBLISH;
4232         }
4233         if (r->guid == NULL) {
4234                 werr = WERR_NOMEM;
4235                 goto out_tmp_free;
4236         }
4237
4238         werr = WERR_OK;
4239 out_tmp_free:
4240         talloc_free(tmp_ctx);
4241         return werr;
4242 }
4243
4244 /********************************************************************
4245  * construct_printer_info8
4246  * fill a spoolss_PrinterInfo8 struct
4247  ********************************************************************/
4248
4249 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4250                                       const struct spoolss_PrinterInfo2 *info2,
4251                                       const char *servername,
4252                                       struct spoolss_DeviceModeInfo *r,
4253                                       int snum)
4254 {
4255         WERROR result;
4256         const char *printername;
4257
4258         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4259         if (!W_ERROR_IS_OK(result)) {
4260                 return result;
4261         }
4262
4263         if (info2->devmode != NULL) {
4264                 result = copy_devicemode(mem_ctx,
4265                                          info2->devmode,
4266                                          &r->devmode);
4267                 if (!W_ERROR_IS_OK(result)) {
4268                         return result;
4269                 }
4270         } else if (lp_default_devmode(snum)) {
4271                 result = spoolss_create_default_devmode(mem_ctx,
4272                                                         info2->printername,
4273                                                         &r->devmode);
4274                 if (!W_ERROR_IS_OK(result)) {
4275                         return result;
4276                 }
4277         } else {
4278                 r->devmode = NULL;
4279                 DEBUG(8,("Returning NULL Devicemode!\n"));
4280         }
4281
4282         compose_devicemode_devicename(r->devmode, printername);
4283
4284         return WERR_OK;
4285 }
4286
4287
4288 /********************************************************************
4289 ********************************************************************/
4290
4291 static bool snum_is_shared_printer(int snum)
4292 {
4293         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_printable(snum));
4294 }
4295
4296 /********************************************************************
4297  Spoolss_enumprinters.
4298 ********************************************************************/
4299
4300 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4301                                            const struct auth_session_info *session_info,
4302                                            struct messaging_context *msg_ctx,
4303                                            const char *servername,
4304                                            uint32_t level,
4305                                            uint32_t flags,
4306                                            union spoolss_PrinterInfo **info_p,
4307                                            uint32_t *count_p)
4308 {
4309         int snum;
4310         int n_services = lp_numservices();
4311         union spoolss_PrinterInfo *info = NULL;
4312         uint32_t count = 0;
4313         WERROR result = WERR_OK;
4314         struct dcerpc_binding_handle *b = NULL;
4315         TALLOC_CTX *tmp_ctx = NULL;
4316
4317         tmp_ctx = talloc_new(mem_ctx);
4318         if (!tmp_ctx) {
4319                 return WERR_NOMEM;
4320         }
4321
4322         *count_p = 0;
4323         *info_p = NULL;
4324
4325         for (snum = 0; snum < n_services; snum++) {
4326
4327                 const char *printer;
4328                 struct spoolss_PrinterInfo2 *info2;
4329
4330                 if (!snum_is_shared_printer(snum)) {
4331                         continue;
4332                 }
4333
4334                 printer = lp_const_servicename(snum);
4335
4336                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4337                         printer, snum));
4338
4339                 if (b == NULL) {
4340                         result = winreg_printer_binding_handle(tmp_ctx,
4341                                                                session_info,
4342                                                                msg_ctx,
4343                                                                &b);
4344                         if (!W_ERROR_IS_OK(result)) {
4345                                 goto out;
4346                         }
4347                 }
4348
4349                 result = winreg_create_printer(tmp_ctx, b,
4350                                                printer);
4351                 if (!W_ERROR_IS_OK(result)) {
4352                         goto out;
4353                 }
4354
4355                 info = talloc_realloc(tmp_ctx, info,
4356                                             union spoolss_PrinterInfo,
4357                                             count + 1);
4358                 if (!info) {
4359                         result = WERR_NOMEM;
4360                         goto out;
4361                 }
4362
4363                 result = winreg_get_printer(tmp_ctx, b,
4364                                             printer, &info2);
4365                 if (!W_ERROR_IS_OK(result)) {
4366                         goto out;
4367                 }
4368
4369                 switch (level) {
4370                 case 0:
4371                         result = construct_printer_info0(info, session_info,
4372                                                          msg_ctx, info2,
4373                                                          servername,
4374                                                          &info[count].info0, snum);
4375                         break;
4376                 case 1:
4377                         result = construct_printer_info1(info, info2, flags,
4378                                                          servername,
4379                                                          &info[count].info1, snum);
4380                         break;
4381                 case 2:
4382                         result = construct_printer_info2(info, msg_ctx, info2,
4383                                                          servername,
4384                                                          &info[count].info2, snum);
4385                         break;
4386                 case 4:
4387                         result = construct_printer_info4(info, info2,
4388                                                          servername,
4389                                                          &info[count].info4, snum);
4390                         break;
4391                 case 5:
4392                         result = construct_printer_info5(info, info2,
4393                                                          servername,
4394                                                          &info[count].info5, snum);
4395                         break;
4396
4397                 default:
4398                         result = WERR_UNKNOWN_LEVEL;
4399                         goto out;
4400                 }
4401
4402                 if (!W_ERROR_IS_OK(result)) {
4403                         goto out;
4404                 }
4405
4406                 count++;
4407         }
4408
4409 out:
4410         if (W_ERROR_IS_OK(result)) {
4411                 *info_p = talloc_move(mem_ctx, &info);
4412                 *count_p = count;
4413         }
4414
4415         talloc_free(tmp_ctx);
4416
4417         return result;
4418 }
4419
4420 /********************************************************************
4421  * handle enumeration of printers at level 0
4422  ********************************************************************/
4423
4424 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4425                                   const struct auth_session_info *session_info,
4426                                   struct messaging_context *msg_ctx,
4427                                   uint32_t flags,
4428                                   const char *servername,
4429                                   union spoolss_PrinterInfo **info,
4430                                   uint32_t *count)
4431 {
4432         DEBUG(4,("enum_all_printers_info_0\n"));
4433
4434         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4435                                             servername, 0, flags, info, count);
4436 }
4437
4438
4439 /********************************************************************
4440 ********************************************************************/
4441
4442 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4443                                        const struct auth_session_info *session_info,
4444                                        struct messaging_context *msg_ctx,
4445                                        const char *servername,
4446                                        uint32_t flags,
4447                                        union spoolss_PrinterInfo **info,
4448                                        uint32_t *count)
4449 {
4450         DEBUG(4,("enum_all_printers_info_1\n"));
4451
4452         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4453                                             servername, 1, flags, info, count);
4454 }
4455
4456 /********************************************************************
4457  enum_all_printers_info_1_local.
4458 *********************************************************************/
4459
4460 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4461                                              const struct auth_session_info *session_info,
4462                                              struct messaging_context *msg_ctx,
4463                                              const char *servername,
4464                                              union spoolss_PrinterInfo **info,
4465                                              uint32_t *count)
4466 {
4467         DEBUG(4,("enum_all_printers_info_1_local\n"));
4468
4469         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4470                                         servername, PRINTER_ENUM_ICON8, info, count);
4471 }
4472
4473 /********************************************************************
4474  enum_all_printers_info_1_name.
4475 *********************************************************************/
4476
4477 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4478                                             const struct auth_session_info *session_info,
4479                                             struct messaging_context *msg_ctx,
4480                                             const char *servername,
4481                                             union spoolss_PrinterInfo **info,
4482                                             uint32_t *count)
4483 {
4484         const char *s = servername;
4485
4486         DEBUG(4,("enum_all_printers_info_1_name\n"));
4487
4488         if (servername != NULL &&
4489             (servername[0] == '\\') && (servername[1] == '\\')) {
4490                 s = servername + 2;
4491         }
4492
4493         if (!is_myname_or_ipaddr(s)) {
4494                 return WERR_INVALID_NAME;
4495         }
4496
4497         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4498                                         servername, PRINTER_ENUM_ICON8, info, count);
4499 }
4500
4501 /********************************************************************
4502  enum_all_printers_info_1_network.
4503 *********************************************************************/
4504
4505 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4506                                                const struct auth_session_info *session_info,
4507                                                struct messaging_context *msg_ctx,
4508                                                const char *servername,
4509                                                union spoolss_PrinterInfo **info,
4510                                                uint32_t *count)
4511 {
4512         const char *s = servername;
4513
4514         DEBUG(4,("enum_all_printers_info_1_network\n"));
4515
4516         /* If we respond to a enum_printers level 1 on our name with flags
4517            set to PRINTER_ENUM_REMOTE with a list of printers then these
4518            printers incorrectly appear in the APW browse list.
4519            Specifically the printers for the server appear at the workgroup
4520            level where all the other servers in the domain are
4521            listed. Windows responds to this call with a
4522            WERR_CAN_NOT_COMPLETE so we should do the same. */
4523
4524         if (servername != NULL &&
4525             (servername[0] == '\\') && (servername[1] == '\\')) {
4526                  s = servername + 2;
4527         }
4528
4529         if (is_myname_or_ipaddr(s)) {
4530                  return WERR_CAN_NOT_COMPLETE;
4531         }
4532
4533         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4534                                         servername, PRINTER_ENUM_NAME, info, count);
4535 }
4536
4537 /********************************************************************
4538  * api_spoolss_enumprinters
4539  *
4540  * called from api_spoolss_enumprinters (see this to understand)
4541  ********************************************************************/
4542
4543 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4544                                        const struct auth_session_info *session_info,
4545                                        struct messaging_context *msg_ctx,
4546                                        const char *servername,
4547                                        union spoolss_PrinterInfo **info,
4548                                        uint32_t *count)
4549 {
4550         DEBUG(4,("enum_all_printers_info_2\n"));
4551
4552         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4553                                             servername, 2, 0, info, count);
4554 }
4555
4556 /********************************************************************
4557  * handle enumeration of printers at level 1
4558  ********************************************************************/
4559
4560 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4561                                   const struct auth_session_info *session_info,
4562                                   struct messaging_context *msg_ctx,
4563                                   uint32_t flags,
4564                                   const char *servername,
4565                                   union spoolss_PrinterInfo **info,
4566                                   uint32_t *count)
4567 {
4568         /* Not all the flags are equals */
4569
4570         if (flags & PRINTER_ENUM_LOCAL) {
4571                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4572                                                       msg_ctx, servername, info, count);
4573         }
4574
4575         if (flags & PRINTER_ENUM_NAME) {
4576                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4577                                                      msg_ctx, servername, info,
4578                                                      count);
4579         }
4580
4581         if (flags & PRINTER_ENUM_NETWORK) {
4582                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4583                                                         msg_ctx, servername, info,
4584                                                         count);
4585         }
4586
4587         return WERR_OK; /* NT4sp5 does that */
4588 }
4589
4590 /********************************************************************
4591  * handle enumeration of printers at level 2
4592  ********************************************************************/
4593
4594 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4595                                   const struct auth_session_info *session_info,
4596                                   struct messaging_context *msg_ctx,
4597                                   uint32_t flags,
4598                                   const char *servername,
4599                                   union spoolss_PrinterInfo **info,
4600                                   uint32_t *count)
4601 {
4602         if (flags & PRINTER_ENUM_LOCAL) {
4603
4604                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4605                                                 servername,
4606                                                 info, count);
4607         }
4608
4609         if (flags & PRINTER_ENUM_NAME) {
4610                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4611                         return WERR_INVALID_NAME;
4612                 }
4613
4614                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4615                                                 servername,
4616                                                 info, count);
4617         }
4618
4619         if (flags & PRINTER_ENUM_REMOTE) {
4620                 return WERR_UNKNOWN_LEVEL;
4621         }
4622
4623         return WERR_OK;
4624 }
4625
4626 /********************************************************************
4627  * handle enumeration of printers at level 4
4628  ********************************************************************/
4629
4630 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4631                                   const struct auth_session_info *session_info,
4632                                   struct messaging_context *msg_ctx,
4633                                   uint32_t flags,
4634                                   const char *servername,
4635                                   union spoolss_PrinterInfo **info,
4636                                   uint32_t *count)
4637 {
4638         DEBUG(4,("enum_all_printers_info_4\n"));
4639
4640         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4641                                             servername, 4, flags, info, count);
4642 }
4643
4644
4645 /********************************************************************
4646  * handle enumeration of printers at level 5
4647  ********************************************************************/
4648
4649 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4650                                   const struct auth_session_info *session_info,
4651                                   struct messaging_context *msg_ctx,
4652                                   uint32_t flags,
4653                                   const char *servername,
4654                                   union spoolss_PrinterInfo **info,
4655                                   uint32_t *count)
4656 {
4657         DEBUG(4,("enum_all_printers_info_5\n"));
4658
4659         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4660                                             servername, 5, flags, info, count);
4661 }
4662
4663 /****************************************************************
4664  _spoolss_EnumPrinters
4665 ****************************************************************/
4666
4667 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4668                              struct spoolss_EnumPrinters *r)
4669 {
4670         const struct auth_session_info *session_info = get_session_info_system();
4671         WERROR result;
4672
4673         /* that's an [in out] buffer */
4674
4675         if (!r->in.buffer && (r->in.offered != 0)) {
4676                 return WERR_INVALID_PARAM;
4677         }
4678
4679         DEBUG(4,("_spoolss_EnumPrinters\n"));
4680
4681         *r->out.needed = 0;
4682         *r->out.count = 0;
4683         *r->out.info = NULL;
4684
4685         /*
4686          * Level 1:
4687          *          flags==PRINTER_ENUM_NAME
4688          *           if name=="" then enumerates all printers
4689          *           if name!="" then enumerate the printer
4690          *          flags==PRINTER_ENUM_REMOTE
4691          *          name is NULL, enumerate printers
4692          * Level 2: name!="" enumerates printers, name can't be NULL
4693          * Level 3: doesn't exist
4694          * Level 4: does a local registry lookup
4695          * Level 5: same as Level 2
4696          */
4697
4698         if (r->in.server && r->in.server[0] == '\0') {
4699                 r->in.server = NULL;
4700         }
4701
4702         switch (r->in.level) {
4703         case 0:
4704                 result = enumprinters_level0(p->mem_ctx, session_info,
4705                                              p->msg_ctx, r->in.flags,
4706                                              r->in.server,
4707                                              r->out.info, r->out.count);
4708                 break;
4709         case 1:
4710                 result = enumprinters_level1(p->mem_ctx, session_info,
4711                                              p->msg_ctx, r->in.flags,
4712                                              r->in.server,
4713                                              r->out.info, r->out.count);
4714                 break;
4715         case 2:
4716                 result = enumprinters_level2(p->mem_ctx, session_info,
4717                                              p->msg_ctx, r->in.flags,
4718                                              r->in.server,
4719                                              r->out.info, r->out.count);
4720                 break;
4721         case 4:
4722                 result = enumprinters_level4(p->mem_ctx, session_info,
4723                                              p->msg_ctx, r->in.flags,
4724                                              r->in.server,
4725                                              r->out.info, r->out.count);
4726                 break;
4727         case 5:
4728                 result = enumprinters_level5(p->mem_ctx, session_info,
4729                                              p->msg_ctx, r->in.flags,
4730                                              r->in.server,
4731                                              r->out.info, r->out.count);
4732                 break;
4733         default:
4734                 return WERR_UNKNOWN_LEVEL;
4735         }
4736
4737         if (!W_ERROR_IS_OK(result)) {
4738                 return result;
4739         }
4740
4741         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4742                                                      spoolss_EnumPrinters,
4743                                                      *r->out.info, r->in.level,
4744                                                      *r->out.count);
4745         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4746         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4747
4748         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4749 }
4750
4751 /****************************************************************
4752  _spoolss_GetPrinter
4753 ****************************************************************/
4754
4755 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4756                            struct spoolss_GetPrinter *r)
4757 {
4758         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4759         struct spoolss_PrinterInfo2 *info2 = NULL;
4760         WERROR result = WERR_OK;
4761         int snum;
4762
4763         /* that's an [in out] buffer */
4764
4765         if (!r->in.buffer && (r->in.offered != 0)) {
4766                 return WERR_INVALID_PARAM;
4767         }
4768
4769         *r->out.needed = 0;
4770
4771         if (Printer == NULL) {
4772                 return WERR_BADFID;
4773         }
4774
4775         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4776                 return WERR_BADFID;
4777         }
4778
4779         result = winreg_get_printer_internal(p->mem_ctx,
4780                                     get_session_info_system(),
4781                                     p->msg_ctx,
4782                                     lp_const_servicename(snum),
4783                                     &info2);
4784         if (!W_ERROR_IS_OK(result)) {
4785                 goto out;
4786         }
4787
4788         switch (r->in.level) {
4789         case 0:
4790                 result = construct_printer_info0(p->mem_ctx,
4791                                                  get_session_info_system(),
4792                                                  p->msg_ctx,
4793                                                  info2,
4794                                                  Printer->servername,
4795                                                  &r->out.info->info0,
4796                                                  snum);
4797                 break;
4798         case 1:
4799                 result = construct_printer_info1(p->mem_ctx, info2,
4800                                                  PRINTER_ENUM_ICON8,
4801                                                  Printer->servername,
4802                                                  &r->out.info->info1, snum);
4803                 break;
4804         case 2:
4805                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4806                                                  Printer->servername,
4807                                                  &r->out.info->info2, snum);
4808                 break;
4809         case 3:
4810                 result = construct_printer_info3(p->mem_ctx, info2,
4811                                                  Printer->servername,
4812                                                  &r->out.info->info3, snum);
4813                 break;
4814         case 4:
4815                 result = construct_printer_info4(p->mem_ctx, info2,
4816                                                  Printer->servername,
4817                                                  &r->out.info->info4, snum);
4818                 break;
4819         case 5:
4820                 result = construct_printer_info5(p->mem_ctx, info2,
4821                                                  Printer->servername,
4822                                                  &r->out.info->info5, snum);
4823                 break;
4824         case 6:
4825                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4826                                                  Printer->servername,
4827                                                  &r->out.info->info6, snum);
4828                 break;
4829         case 7:
4830                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4831                                                  Printer->servername,
4832                                                  &r->out.info->info7, snum);
4833                 break;
4834         case 8:
4835                 result = construct_printer_info8(p->mem_ctx, info2,
4836                                                  Printer->servername,
4837                                                  &r->out.info->info8, snum);
4838                 break;
4839         default:
4840                 result = WERR_UNKNOWN_LEVEL;
4841                 break;
4842         }
4843         TALLOC_FREE(info2);
4844
4845  out:
4846         if (!W_ERROR_IS_OK(result)) {
4847                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4848                           r->in.level, win_errstr(result)));
4849                 TALLOC_FREE(r->out.info);
4850                 return result;
4851         }
4852
4853         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4854                                                r->out.info, r->in.level);
4855         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4856
4857         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4858 }
4859
4860 /********************************************************************
4861  ********************************************************************/
4862
4863 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4864         do { \
4865                 if (in && strlen(in)) { \
4866                         out = talloc_strdup(mem_ctx, in); \
4867                 } else { \
4868                         out = talloc_strdup(mem_ctx, ""); \
4869                 } \
4870                 W_ERROR_HAVE_NO_MEMORY(out); \
4871         } while (0);
4872
4873 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4874         do { \
4875                 if (in && strlen(in)) { \
4876                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4877                 } else { \
4878                         out = talloc_strdup(mem_ctx, ""); \
4879                 } \
4880                 W_ERROR_HAVE_NO_MEMORY(out); \
4881         } while (0);
4882
4883 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4884                                                   const char **string_array,
4885                                                   const char ***presult,
4886                                                   const char *cservername,
4887                                                   const char *arch,
4888                                                   int version)
4889 {
4890         int i, num_strings = 0;
4891         const char **array = NULL;
4892
4893         if (string_array == NULL) {
4894                 return WERR_INVALID_PARAMETER;
4895         }
4896
4897         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4898                 const char *str = NULL;
4899
4900                 if (cservername == NULL || arch == NULL) {
4901                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4902                 } else {
4903                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4904                 }
4905
4906                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4907                         TALLOC_FREE(array);
4908                         return WERR_NOMEM;
4909                 }
4910         }
4911
4912         if (i > 0) {
4913                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4914                              &array, &num_strings);
4915         }
4916
4917         if (presult != NULL) {
4918                 *presult = array;
4919         } else {
4920                 talloc_free(array);
4921         }
4922
4923         return WERR_OK;
4924 }
4925
4926 /********************************************************************
4927  * fill a spoolss_DriverInfo1 struct
4928  ********************************************************************/
4929
4930 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4931                                         struct spoolss_DriverInfo1 *r,
4932                                         const struct spoolss_DriverInfo8 *driver,
4933                                         const char *servername)
4934 {
4935         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4936         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4937
4938         return WERR_OK;
4939 }
4940
4941 /********************************************************************
4942  * fill a spoolss_DriverInfo2 struct
4943  ********************************************************************/
4944
4945 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4946                                         struct spoolss_DriverInfo2 *r,
4947                                         const struct spoolss_DriverInfo8 *driver,
4948                                         const char *servername)
4949
4950 {
4951         const char *cservername = canon_servername(servername);
4952
4953         r->version              = driver->version;
4954
4955         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4956         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4957         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4958         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4959
4960         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4961                                driver->architecture,
4962                                driver->version,
4963                                driver->driver_path,
4964                                r->driver_path);
4965
4966         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4967                                driver->architecture,
4968                                driver->version,
4969                                driver->data_file,
4970                                r->data_file);
4971
4972         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4973                                driver->architecture,
4974                                driver->version,
4975                                driver->config_file,
4976                                r->config_file);
4977
4978         return WERR_OK;
4979 }
4980
4981 /********************************************************************
4982  * fill a spoolss_DriverInfo3 struct
4983  ********************************************************************/
4984
4985 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4986                                         struct spoolss_DriverInfo3 *r,
4987                                         const struct spoolss_DriverInfo8 *driver,
4988                                         const char *servername)
4989 {
4990         const char *cservername = canon_servername(servername);
4991
4992         r->version              = driver->version;
4993
4994         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4995         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4996         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4997         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4998
4999         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5000                                driver->architecture,
5001                                driver->version,
5002                                driver->driver_path,
5003                                r->driver_path);
5004
5005         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5006                                driver->architecture,
5007                                driver->version,
5008                                driver->data_file,
5009                                r->data_file);
5010
5011         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5012                                driver->architecture,
5013                                driver->version,
5014                                driver->config_file,
5015                                r->config_file);
5016
5017         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5018                                driver->architecture,
5019                                driver->version,
5020                                driver->help_file,
5021                                r->help_file);
5022
5023         FILL_DRIVER_STRING(mem_ctx,
5024                            driver->monitor_name,
5025                            r->monitor_name);
5026
5027         FILL_DRIVER_STRING(mem_ctx,
5028                            driver->default_datatype,
5029                            r->default_datatype);
5030
5031         return string_array_from_driver_info(mem_ctx,
5032                                              driver->dependent_files,
5033                                              &r->dependent_files,
5034                                              cservername,
5035                                              driver->architecture,
5036                                              driver->version);
5037 }
5038
5039 /********************************************************************
5040  * fill a spoolss_DriverInfo4 struct
5041  ********************************************************************/
5042
5043 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5044                                         struct spoolss_DriverInfo4 *r,
5045                                         const struct spoolss_DriverInfo8 *driver,
5046                                         const char *servername)
5047 {
5048         const char *cservername = canon_servername(servername);
5049         WERROR result;
5050
5051         r->version              = driver->version;
5052
5053         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5054         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5055         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5056         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5057
5058         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5059                                driver->architecture,
5060                                driver->version,
5061                                driver->driver_path,
5062                                r->driver_path);
5063
5064         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5065                                driver->architecture,
5066                                driver->version,
5067                                driver->data_file,
5068                                r->data_file);
5069
5070         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5071                                driver->architecture,
5072                                driver->version,
5073                                driver->config_file,
5074                                r->config_file);
5075
5076         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5077                                driver->architecture,
5078                                driver->version,
5079                                driver->help_file,
5080                                r->help_file);
5081
5082         result = string_array_from_driver_info(mem_ctx,
5083                                                driver->dependent_files,
5084                                                &r->dependent_files,
5085                                                cservername,
5086                                                driver->architecture,
5087                                                driver->version);
5088         if (!W_ERROR_IS_OK(result)) {
5089                 return result;
5090         }
5091
5092         FILL_DRIVER_STRING(mem_ctx,
5093                            driver->monitor_name,
5094                            r->monitor_name);
5095
5096         FILL_DRIVER_STRING(mem_ctx,
5097                            driver->default_datatype,
5098                            r->default_datatype);
5099
5100
5101         result = string_array_from_driver_info(mem_ctx,
5102                                                driver->previous_names,
5103                                                &r->previous_names,
5104                                                NULL, NULL, 0);
5105
5106         return result;
5107 }
5108
5109 /********************************************************************
5110  * fill a spoolss_DriverInfo5 struct
5111  ********************************************************************/
5112
5113 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5114                                         struct spoolss_DriverInfo5 *r,
5115                                         const struct spoolss_DriverInfo8 *driver,
5116                                         const char *servername)
5117 {
5118         const char *cservername = canon_servername(servername);
5119
5120         r->version              = driver->version;
5121
5122         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5123         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5124         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5125         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5126
5127         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5128                                driver->architecture,
5129                                driver->version,
5130                                driver->driver_path,
5131                                r->driver_path);
5132
5133         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5134                                driver->architecture,
5135                                driver->version,
5136                                driver->data_file,
5137                                r->data_file);
5138
5139         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5140                                driver->architecture,
5141                                driver->version,
5142                                driver->config_file,
5143                                r->config_file);
5144
5145         r->driver_attributes    = 0;
5146         r->config_version       = 0;
5147         r->driver_version       = 0;
5148
5149         return WERR_OK;
5150 }
5151 /********************************************************************
5152  * fill a spoolss_DriverInfo6 struct
5153  ********************************************************************/
5154
5155 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5156                                         struct spoolss_DriverInfo6 *r,
5157                                         const struct spoolss_DriverInfo8 *driver,
5158                                         const char *servername)
5159 {
5160         const char *cservername = canon_servername(servername);
5161         WERROR result;
5162
5163         r->version              = driver->version;
5164
5165         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5166         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5167         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5168         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5169
5170         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5171                                driver->architecture,
5172                                driver->version,
5173                                driver->driver_path,
5174                                r->driver_path);
5175
5176         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5177                                driver->architecture,
5178                                driver->version,
5179                                driver->data_file,
5180                                r->data_file);
5181
5182         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5183                                driver->architecture,
5184                                driver->version,
5185                                driver->config_file,
5186                                r->config_file);
5187
5188         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5189                                driver->architecture,
5190                                driver->version,
5191                                driver->help_file,
5192                                r->help_file);
5193
5194         FILL_DRIVER_STRING(mem_ctx,
5195                            driver->monitor_name,
5196                            r->monitor_name);
5197
5198         FILL_DRIVER_STRING(mem_ctx,
5199                            driver->default_datatype,
5200                            r->default_datatype);
5201
5202         result = string_array_from_driver_info(mem_ctx,
5203                                                driver->dependent_files,
5204                                                &r->dependent_files,
5205                                                cservername,
5206                                                driver->architecture,
5207                                                driver->version);
5208         if (!W_ERROR_IS_OK(result)) {
5209                 return result;
5210         }
5211
5212         result = string_array_from_driver_info(mem_ctx,
5213                                                driver->previous_names,
5214                                                &r->previous_names,
5215                                                NULL, NULL, 0);
5216         if (!W_ERROR_IS_OK(result)) {
5217                 return result;
5218         }
5219
5220         r->driver_date          = driver->driver_date;
5221         r->driver_version       = driver->driver_version;
5222
5223         FILL_DRIVER_STRING(mem_ctx,
5224                            driver->manufacturer_name,
5225                            r->manufacturer_name);
5226         FILL_DRIVER_STRING(mem_ctx,
5227                            driver->manufacturer_url,
5228                            r->manufacturer_url);
5229         FILL_DRIVER_STRING(mem_ctx,
5230                            driver->hardware_id,
5231                            r->hardware_id);
5232         FILL_DRIVER_STRING(mem_ctx,
5233                            driver->provider,
5234                            r->provider);
5235
5236         return WERR_OK;
5237 }
5238
5239 /********************************************************************
5240  * fill a spoolss_DriverInfo8 struct
5241  ********************************************************************/
5242
5243 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5244                                         struct spoolss_DriverInfo8 *r,
5245                                         const struct spoolss_DriverInfo8 *driver,
5246                                         const char *servername)
5247 {
5248         const char *cservername = canon_servername(servername);
5249         WERROR result;
5250
5251         r->version              = driver->version;
5252
5253         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5254         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5255         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5256         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5257
5258         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5259                                driver->architecture,
5260                                driver->version,
5261                                driver->driver_path,
5262                                r->driver_path);
5263
5264         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5265                                driver->architecture,
5266                                driver->version,
5267                                driver->data_file,
5268                                r->data_file);
5269
5270         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5271                                driver->architecture,
5272                                driver->version,
5273                                driver->config_file,
5274                                r->config_file);
5275
5276         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5277                                driver->architecture,
5278                                driver->version,
5279                                driver->help_file,
5280                                r->help_file);
5281
5282         FILL_DRIVER_STRING(mem_ctx,
5283                            driver->monitor_name,
5284                            r->monitor_name);
5285
5286         FILL_DRIVER_STRING(mem_ctx,
5287                            driver->default_datatype,
5288                            r->default_datatype);
5289
5290         result = string_array_from_driver_info(mem_ctx,
5291                                                driver->dependent_files,
5292                                                &r->dependent_files,
5293                                                cservername,
5294                                                driver->architecture,
5295                                                driver->version);
5296         if (!W_ERROR_IS_OK(result)) {
5297                 return result;
5298         }
5299
5300         result = string_array_from_driver_info(mem_ctx,
5301                                                driver->previous_names,
5302                                                &r->previous_names,
5303                                                NULL, NULL, 0);
5304         if (!W_ERROR_IS_OK(result)) {
5305                 return result;
5306         }
5307
5308         r->driver_date          = driver->driver_date;
5309         r->driver_version       = driver->driver_version;
5310
5311         FILL_DRIVER_STRING(mem_ctx,
5312                            driver->manufacturer_name,
5313                            r->manufacturer_name);
5314         FILL_DRIVER_STRING(mem_ctx,
5315                            driver->manufacturer_url,
5316                            r->manufacturer_url);
5317         FILL_DRIVER_STRING(mem_ctx,
5318                            driver->hardware_id,
5319                            r->hardware_id);
5320         FILL_DRIVER_STRING(mem_ctx,
5321                            driver->provider,
5322                            r->provider);
5323
5324         FILL_DRIVER_STRING(mem_ctx,
5325                            driver->print_processor,
5326                            r->print_processor);
5327         FILL_DRIVER_STRING(mem_ctx,
5328                            driver->vendor_setup,
5329                            r->vendor_setup);
5330
5331         result = string_array_from_driver_info(mem_ctx,
5332                                                driver->color_profiles,
5333                                                &r->color_profiles,
5334                                                NULL, NULL, 0);
5335         if (!W_ERROR_IS_OK(result)) {
5336                 return result;
5337         }
5338
5339         FILL_DRIVER_STRING(mem_ctx,
5340                            driver->inf_path,
5341                            r->inf_path);
5342
5343         r->printer_driver_attributes    = driver->printer_driver_attributes;
5344
5345         result = string_array_from_driver_info(mem_ctx,
5346                                                driver->core_driver_dependencies,
5347                                                &r->core_driver_dependencies,
5348                                                NULL, NULL, 0);
5349         if (!W_ERROR_IS_OK(result)) {
5350                 return result;
5351         }
5352
5353         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5354         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5355
5356         return WERR_OK;
5357 }
5358
5359 #if 0 /* disabled until marshalling issues are resolved - gd */
5360 /********************************************************************
5361  ********************************************************************/
5362
5363 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5364                                           struct spoolss_DriverFileInfo *r,
5365                                           const char *cservername,
5366                                           const char *file_name,
5367                                           enum spoolss_DriverFileType file_type,
5368                                           uint32_t file_version)
5369 {
5370         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5371                                           cservername, file_name);
5372         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5373         r->file_type    = file_type;
5374         r->file_version = file_version;
5375
5376         return WERR_OK;
5377 }
5378
5379 /********************************************************************
5380  ********************************************************************/
5381
5382 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5383                                                  const struct spoolss_DriverInfo8 *driver,
5384                                                  const char *cservername,
5385                                                  struct spoolss_DriverFileInfo **info_p,
5386                                                  uint32_t *count_p)
5387 {
5388         struct spoolss_DriverFileInfo *info = NULL;
5389         uint32_t count = 0;
5390         WERROR result;
5391         uint32_t i;
5392
5393         *info_p = NULL;
5394         *count_p = 0;
5395
5396         if (strlen(driver->driver_path)) {
5397                 info = talloc_realloc(mem_ctx, info,
5398                                             struct spoolss_DriverFileInfo,
5399                                             count + 1);
5400                 W_ERROR_HAVE_NO_MEMORY(info);
5401                 result = fill_spoolss_DriverFileInfo(info,
5402                                                      &info[count],
5403                                                      cservername,
5404                                                      driver->driver_path,
5405                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5406                                                      0);
5407                 W_ERROR_NOT_OK_RETURN(result);
5408                 count++;
5409         }
5410
5411         if (strlen(driver->config_file)) {
5412                 info = talloc_realloc(mem_ctx, info,
5413                                             struct spoolss_DriverFileInfo,
5414                                             count + 1);
5415                 W_ERROR_HAVE_NO_MEMORY(info);
5416                 result = fill_spoolss_DriverFileInfo(info,
5417                                                      &info[count],
5418                                                      cservername,
5419                                                      driver->config_file,
5420                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5421                                                      0);
5422                 W_ERROR_NOT_OK_RETURN(result);
5423                 count++;
5424         }
5425
5426         if (strlen(driver->data_file)) {
5427                 info = talloc_realloc(mem_ctx, info,
5428                                             struct spoolss_DriverFileInfo,
5429                                             count + 1);
5430                 W_ERROR_HAVE_NO_MEMORY(info);
5431                 result = fill_spoolss_DriverFileInfo(info,
5432                                                      &info[count],
5433                                                      cservername,
5434                                                      driver->data_file,
5435                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5436                                                      0);
5437                 W_ERROR_NOT_OK_RETURN(result);
5438                 count++;
5439         }
5440
5441         if (strlen(driver->help_file)) {
5442                 info = talloc_realloc(mem_ctx, info,
5443                                             struct spoolss_DriverFileInfo,
5444                                             count + 1);
5445                 W_ERROR_HAVE_NO_MEMORY(info);
5446                 result = fill_spoolss_DriverFileInfo(info,
5447                                                      &info[count],
5448                                                      cservername,
5449                                                      driver->help_file,
5450                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5451                                                      0);
5452                 W_ERROR_NOT_OK_RETURN(result);
5453                 count++;
5454         }
5455
5456         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5457                 info = talloc_realloc(mem_ctx, info,
5458                                             struct spoolss_DriverFileInfo,
5459                                             count + 1);
5460                 W_ERROR_HAVE_NO_MEMORY(info);
5461                 result = fill_spoolss_DriverFileInfo(info,
5462                                                      &info[count],
5463                                                      cservername,
5464                                                      driver->dependent_files[i],
5465                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5466                                                      0);
5467                 W_ERROR_NOT_OK_RETURN(result);
5468                 count++;
5469         }
5470
5471         *info_p = info;
5472         *count_p = count;
5473
5474         return WERR_OK;
5475 }
5476
5477 /********************************************************************
5478  * fill a spoolss_DriverInfo101 struct
5479  ********************************************************************/
5480
5481 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5482                                           struct spoolss_DriverInfo101 *r,
5483                                           const struct spoolss_DriverInfo8 *driver,
5484                                           const char *servername)
5485 {
5486         const char *cservername = canon_servername(servername);
5487         WERROR result;
5488
5489         r->version              = driver->version;
5490
5491         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5492         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5493         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5494         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5495
5496         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5497                                                     cservername,
5498                                                     &r->file_info,
5499                                                     &r->file_count);
5500         if (!W_ERROR_IS_OK(result)) {
5501                 return result;
5502         }
5503
5504         FILL_DRIVER_STRING(mem_ctx,
5505                            driver->monitor_name,
5506                            r->monitor_name);
5507
5508         FILL_DRIVER_STRING(mem_ctx,
5509                            driver->default_datatype,
5510                            r->default_datatype);
5511
5512         result = string_array_from_driver_info(mem_ctx,
5513                                                driver->previous_names,
5514                                                &r->previous_names,
5515                                                NULL, NULL, 0);
5516         if (!W_ERROR_IS_OK(result)) {
5517                 return result;
5518         }
5519
5520         r->driver_date          = driver->driver_date;
5521         r->driver_version       = driver->driver_version;
5522
5523         FILL_DRIVER_STRING(mem_ctx,
5524                            driver->manufacturer_name,
5525                            r->manufacturer_name);
5526         FILL_DRIVER_STRING(mem_ctx,
5527                            driver->manufacturer_url,
5528                            r->manufacturer_url);
5529         FILL_DRIVER_STRING(mem_ctx,
5530                            driver->hardware_id,
5531                            r->hardware_id);
5532         FILL_DRIVER_STRING(mem_ctx,
5533                            driver->provider,
5534                            r->provider);
5535
5536         return WERR_OK;
5537 }
5538 #endif
5539 /********************************************************************
5540  ********************************************************************/
5541
5542 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5543                                                   const struct auth_session_info *session_info,
5544                                                   struct messaging_context *msg_ctx,
5545                                                   uint32_t level,
5546                                                   union spoolss_DriverInfo *r,
5547                                                   int snum,
5548                                                   const char *servername,
5549                                                   const char *architecture,
5550                                                   uint32_t version)
5551 {
5552         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5553         struct spoolss_DriverInfo8 *driver;
5554         WERROR result;
5555         struct dcerpc_binding_handle *b;
5556         TALLOC_CTX *tmp_ctx = NULL;
5557
5558         if (level == 101) {
5559                 return WERR_UNKNOWN_LEVEL;
5560         }
5561
5562         tmp_ctx = talloc_new(mem_ctx);
5563         if (!tmp_ctx) {
5564                 return WERR_NOMEM;
5565         }
5566
5567         result = winreg_printer_binding_handle(tmp_ctx,
5568                                                session_info,
5569                                                msg_ctx,
5570                                                &b);
5571         if (!W_ERROR_IS_OK(result)) {
5572                 goto done;
5573         }
5574
5575         result = winreg_get_printer(tmp_ctx, b,
5576                                     lp_const_servicename(snum),
5577                                     &pinfo2);
5578
5579         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5580                 win_errstr(result)));
5581
5582         if (!W_ERROR_IS_OK(result)) {
5583                 result = WERR_INVALID_PRINTER_NAME;
5584                 goto done;
5585         }
5586
5587         result = winreg_get_driver(tmp_ctx, b,
5588                                    architecture,
5589                                    pinfo2->drivername, version, &driver);
5590
5591         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5592                 win_errstr(result)));
5593
5594         if (!W_ERROR_IS_OK(result)) {
5595                 /*
5596                  * Is this a W2k client ?
5597                  */
5598
5599                 if (version < 3) {
5600                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5601                         goto done;
5602                 }
5603
5604                 /* Yes - try again with a WinNT driver. */
5605                 version = 2;
5606                 result = winreg_get_driver(tmp_ctx, b,
5607                                            architecture,
5608                                            pinfo2->drivername,
5609                                            version, &driver);
5610                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5611                         win_errstr(result)));
5612                 if (!W_ERROR_IS_OK(result)) {
5613                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5614                         goto done;
5615                 }
5616         }
5617
5618         /* these are allocated on mem_ctx and not tmp_ctx because they are
5619          * the 'return value' and need to utlive this call */
5620         switch (level) {
5621         case 1:
5622                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5623                 break;
5624         case 2:
5625                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5626                 break;
5627         case 3:
5628                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5629                 break;
5630         case 4:
5631                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5632                 break;
5633         case 5:
5634                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5635                 break;
5636         case 6:
5637                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5638                 break;
5639         case 8:
5640                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5641                 break;
5642 #if 0 /* disabled until marshalling issues are resolved - gd */
5643         case 101:
5644                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5645                 break;
5646 #endif
5647         default:
5648                 result = WERR_UNKNOWN_LEVEL;
5649                 break;
5650         }
5651
5652 done:
5653         talloc_free(tmp_ctx);
5654         return result;
5655 }
5656
5657 /****************************************************************
5658  _spoolss_GetPrinterDriver2
5659 ****************************************************************/
5660
5661 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5662                                   struct spoolss_GetPrinterDriver2 *r)
5663 {
5664         struct printer_handle *printer;
5665         WERROR result;
5666         uint32_t version = r->in.client_major_version;
5667
5668         int snum;
5669
5670         /* that's an [in out] buffer */
5671
5672         if (!r->in.buffer && (r->in.offered != 0)) {
5673                 return WERR_INVALID_PARAM;
5674         }
5675
5676         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5677
5678         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5679                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5680                 return WERR_INVALID_PRINTER_NAME;
5681         }
5682
5683         *r->out.needed = 0;
5684         *r->out.server_major_version = 0;
5685         *r->out.server_minor_version = 0;
5686
5687         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5688                 return WERR_BADFID;
5689         }
5690
5691         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5692                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5693                         "downgrading to v3\n"));
5694                 version = SPOOLSS_DRIVER_VERSION_200X;
5695         }
5696
5697         result = construct_printer_driver_info_level(p->mem_ctx,
5698                                                      get_session_info_system(),
5699                                                      p->msg_ctx,
5700                                                      r->in.level, r->out.info,
5701                                                      snum, printer->servername,
5702                                                      r->in.architecture,
5703                                                      version);
5704         if (!W_ERROR_IS_OK(result)) {
5705                 TALLOC_FREE(r->out.info);
5706                 return result;
5707         }
5708
5709         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5710                                                r->out.info, r->in.level);
5711         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5712
5713         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5714 }
5715
5716
5717 /****************************************************************
5718  _spoolss_StartPagePrinter
5719 ****************************************************************/
5720
5721 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5722                                  struct spoolss_StartPagePrinter *r)
5723 {
5724         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5725
5726         if (!Printer) {
5727                 DEBUG(3,("_spoolss_StartPagePrinter: "
5728                         "Error in startpageprinter printer handle\n"));
5729                 return WERR_BADFID;
5730         }
5731
5732         Printer->page_started = true;
5733         return WERR_OK;
5734 }
5735
5736 /****************************************************************
5737  _spoolss_EndPagePrinter
5738 ****************************************************************/
5739
5740 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5741                                struct spoolss_EndPagePrinter *r)
5742 {
5743         int snum;
5744
5745         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5746
5747         if (!Printer) {
5748                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5749                         OUR_HANDLE(r->in.handle)));
5750                 return WERR_BADFID;
5751         }
5752
5753         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5754                 return WERR_BADFID;
5755
5756         Printer->page_started = false;
5757         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5758
5759         return WERR_OK;
5760 }
5761
5762 /****************************************************************
5763  _spoolss_StartDocPrinter
5764 ****************************************************************/
5765
5766 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5767                                 struct spoolss_StartDocPrinter *r)
5768 {
5769         struct spoolss_DocumentInfo1 *info_1;
5770         int snum;
5771         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5772         WERROR werr;
5773         char *rhost;
5774         int rc;
5775
5776         if (!Printer) {
5777                 DEBUG(2,("_spoolss_StartDocPrinter: "
5778                         "Invalid handle (%s:%u:%u)\n",
5779                         OUR_HANDLE(r->in.handle)));
5780                 return WERR_BADFID;
5781         }
5782
5783         if (Printer->jobid) {
5784                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5785                           "StartDocPrinter called twice! "
5786                           "(existing jobid = %d)\n", Printer->jobid));
5787                 return WERR_INVALID_HANDLE;
5788         }
5789
5790         if (r->in.info_ctr->level != 1) {
5791                 return WERR_UNKNOWN_LEVEL;
5792         }
5793
5794         info_1 = r->in.info_ctr->info.info1;
5795
5796         /*
5797          * a nice thing with NT is it doesn't listen to what you tell it.
5798          * when asked to send _only_ RAW datas, it tries to send datas
5799          * in EMF format.
5800          *
5801          * So I add checks like in NT Server ...
5802          */
5803
5804         if (info_1->datatype) {
5805                 /*
5806                  * The v4 driver model used in Windows 8 declares print jobs
5807                  * intended to bypass the XPS processing layer by setting
5808                  * datatype to "XPS_PASS" instead of "RAW".
5809                  */
5810                 if ((strcmp(info_1->datatype, "RAW") != 0)
5811                  && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5812                         *r->out.job_id = 0;
5813                         return WERR_INVALID_DATATYPE;
5814                 }
5815         }
5816
5817         /* get the share number of the printer */
5818         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5819                 return WERR_BADFID;
5820         }
5821
5822         rc = get_remote_hostname(p->remote_address,
5823                                  &rhost,
5824                                  p->mem_ctx);
5825         if (rc < 0) {
5826                 return WERR_NOMEM;
5827         }
5828         if (strequal(rhost,"UNKNOWN")) {
5829                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5830                                                          p->mem_ctx);
5831                 if (rhost == NULL) {
5832                         return WERR_NOMEM;
5833                 }
5834         }
5835
5836         werr = print_job_start(p->session_info,
5837                                p->msg_ctx,
5838                                rhost,
5839                                snum,
5840                                info_1->document_name,
5841                                info_1->output_file,
5842                                Printer->devmode,
5843                                &Printer->jobid);
5844
5845         /* An error occured in print_job_start() so return an appropriate
5846            NT error code. */
5847
5848         if (!W_ERROR_IS_OK(werr)) {
5849                 return werr;
5850         }
5851
5852         Printer->document_started = true;
5853         *r->out.job_id = Printer->jobid;
5854
5855         return WERR_OK;
5856 }
5857
5858 /****************************************************************
5859  _spoolss_EndDocPrinter
5860 ****************************************************************/
5861
5862 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5863                               struct spoolss_EndDocPrinter *r)
5864 {
5865         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5866         NTSTATUS status;
5867         int snum;
5868
5869         if (!Printer) {
5870                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5871                         OUR_HANDLE(r->in.handle)));
5872                 return WERR_BADFID;
5873         }
5874
5875         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5876                 return WERR_BADFID;
5877         }
5878
5879         Printer->document_started = false;
5880         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5881         if (!NT_STATUS_IS_OK(status)) {
5882                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5883                           "print_job_end failed [%s]\n",
5884                           nt_errstr(status)));
5885         }
5886
5887         Printer->jobid = 0;
5888         return ntstatus_to_werror(status);
5889 }
5890
5891 /****************************************************************
5892  _spoolss_WritePrinter
5893 ****************************************************************/
5894
5895 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5896                              struct spoolss_WritePrinter *r)
5897 {
5898         ssize_t buffer_written;
5899         int snum;
5900         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5901
5902         if (!Printer) {
5903                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5904                         OUR_HANDLE(r->in.handle)));
5905                 *r->out.num_written = r->in._data_size;
5906                 return WERR_BADFID;
5907         }
5908
5909         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5910                 return WERR_BADFID;
5911
5912         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5913         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5914                                                    snum, Printer->jobid,
5915                                                    (const char *)r->in.data.data,
5916                                                    (size_t)r->in._data_size);
5917         if (buffer_written == (ssize_t)-1) {
5918                 *r->out.num_written = 0;
5919                 if (errno == ENOSPC)
5920                         return WERR_NO_SPOOL_SPACE;
5921                 else
5922                         return WERR_ACCESS_DENIED;
5923         }
5924
5925         *r->out.num_written = r->in._data_size;
5926
5927         return WERR_OK;
5928 }
5929
5930 /********************************************************************
5931  * api_spoolss_getprinter
5932  * called from the spoolss dispatcher
5933  *
5934  ********************************************************************/
5935
5936 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5937                               struct pipes_struct *p)
5938 {
5939         const struct auth_session_info *session_info = p->session_info;
5940         int snum;
5941         WERROR errcode = WERR_BADFUNC;
5942         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5943
5944         if (!Printer) {
5945                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5946                         OUR_HANDLE(handle)));
5947                 return WERR_BADFID;
5948         }
5949
5950         if (!get_printer_snum(p, handle, &snum, NULL))
5951                 return WERR_BADFID;
5952
5953         switch (command) {
5954         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5955                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5956                 break;
5957         case SPOOLSS_PRINTER_CONTROL_RESUME:
5958         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5959                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5960                 break;
5961         case SPOOLSS_PRINTER_CONTROL_PURGE:
5962                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5963                 break;
5964         default:
5965                 return WERR_UNKNOWN_LEVEL;
5966         }
5967
5968         return errcode;
5969 }
5970
5971
5972 /****************************************************************
5973  _spoolss_AbortPrinter
5974  * From MSDN: "Deletes printer's spool file if printer is configured
5975  * for spooling"
5976 ****************************************************************/
5977
5978 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5979                              struct spoolss_AbortPrinter *r)
5980 {
5981         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5982         int             snum;
5983         WERROR          errcode = WERR_OK;
5984
5985         if (!Printer) {
5986                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5987                         OUR_HANDLE(r->in.handle)));
5988                 return WERR_BADFID;
5989         }
5990
5991         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5992                 return WERR_BADFID;
5993
5994         if (!Printer->document_started) {
5995                 return WERR_SPL_NO_STARTDOC;
5996         }
5997
5998         errcode = print_job_delete(p->session_info,
5999                                    p->msg_ctx,
6000                                    snum,
6001                                    Printer->jobid);
6002
6003         return errcode;
6004 }
6005
6006 /********************************************************************
6007  * called by spoolss_api_setprinter
6008  * when updating a printer description
6009  ********************************************************************/
6010
6011 static WERROR update_printer_sec(struct policy_handle *handle,
6012                                  struct pipes_struct *p,
6013                                  struct sec_desc_buf *secdesc_ctr)
6014 {
6015         struct spoolss_security_descriptor *new_secdesc = NULL;
6016         struct spoolss_security_descriptor *old_secdesc = NULL;
6017         const char *printer;
6018         WERROR result;
6019         int snum;
6020         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6021         struct dcerpc_binding_handle *b;
6022         TALLOC_CTX *tmp_ctx = NULL;
6023
6024         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6025                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6026                          OUR_HANDLE(handle)));
6027
6028                 result = WERR_BADFID;
6029                 goto done;
6030         }
6031
6032         if (secdesc_ctr == NULL) {
6033                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6034                 result = WERR_INVALID_PARAM;
6035                 goto done;
6036         }
6037         printer = lp_const_servicename(snum);
6038
6039         /* Check the user has permissions to change the security
6040            descriptor.  By experimentation with two NT machines, the user
6041            requires Full Access to the printer to change security
6042            information. */
6043
6044         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6045                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6046                 result = WERR_ACCESS_DENIED;
6047                 goto done;
6048         }
6049
6050         tmp_ctx = talloc_new(p->mem_ctx);
6051         if (!tmp_ctx) {
6052                 return WERR_NOMEM;
6053         }
6054
6055         result = winreg_printer_binding_handle(tmp_ctx,
6056                                                get_session_info_system(),
6057                                                p->msg_ctx,
6058                                                &b);
6059         if (!W_ERROR_IS_OK(result)) {
6060                 goto done;
6061         }
6062
6063         /* NT seems to like setting the security descriptor even though
6064            nothing may have actually changed. */
6065         result = winreg_get_printer_secdesc(tmp_ctx, b,
6066                                             printer,
6067                                             &old_secdesc);
6068         if (!W_ERROR_IS_OK(result)) {
6069                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6070                 result = WERR_BADFID;
6071                 goto done;
6072         }
6073
6074         if (DEBUGLEVEL >= 10) {
6075                 struct security_acl *the_acl;
6076                 int i;
6077
6078                 the_acl = old_secdesc->dacl;
6079                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6080                            printer, the_acl->num_aces));
6081
6082                 for (i = 0; i < the_acl->num_aces; i++) {
6083                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6084                                            &the_acl->aces[i].trustee),
6085                                   the_acl->aces[i].access_mask));
6086                 }
6087
6088                 the_acl = secdesc_ctr->sd->dacl;
6089
6090                 if (the_acl) {
6091                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6092                                    printer, the_acl->num_aces));
6093
6094                         for (i = 0; i < the_acl->num_aces; i++) {
6095                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6096                                                    &the_acl->aces[i].trustee),
6097                                            the_acl->aces[i].access_mask));
6098                         }
6099                 } else {
6100                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6101                 }
6102         }
6103
6104         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6105         if (new_secdesc == NULL) {
6106                 result = WERR_NOMEM;
6107                 goto done;
6108         }
6109
6110         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6111                 result = WERR_OK;
6112                 goto done;
6113         }
6114
6115         result = winreg_set_printer_secdesc(tmp_ctx, b,
6116                                             printer,
6117                                             new_secdesc);
6118
6119 done:
6120         talloc_free(tmp_ctx);
6121         return result;
6122 }
6123
6124 /********************************************************************
6125  Canonicalize printer info from a client
6126  ********************************************************************/
6127
6128 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6129                              struct spoolss_SetPrinterInfo2 *info2,
6130                              int snum)
6131 {
6132         fstring printername;
6133         const char *p;
6134
6135         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6136                 "portname=%s drivername=%s comment=%s location=%s\n",
6137                 info2->servername, info2->printername, info2->sharename,
6138                 info2->portname, info2->drivername, info2->comment,
6139                 info2->location));
6140
6141         /* we force some elements to "correct" values */
6142         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6143         if (info2->servername == NULL) {
6144                 return false;
6145         }
6146         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6147         if (info2->sharename == NULL) {
6148                 return false;
6149         }
6150
6151         /* check to see if we allow printername != sharename */
6152         if (lp_force_printername(snum)) {
6153                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6154                                         lp_netbios_name(), info2->sharename);
6155         } else {
6156                 /* make sure printername is in \\server\printername format */
6157                 fstrcpy(printername, info2->printername);
6158                 p = printername;
6159                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6160                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6161                                 p++;
6162                 }
6163
6164                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6165                                         lp_netbios_name(), p);
6166         }
6167         if (info2->printername == NULL) {
6168                 return false;
6169         }
6170
6171         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6172         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6173
6174         return true;
6175 }
6176
6177 /****************************************************************************
6178 ****************************************************************************/
6179
6180 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6181 {
6182         char *cmd = lp_addport_cmd(talloc_tos());
6183         char *command = NULL;
6184         int ret;
6185         bool is_print_op = false;
6186
6187         if ( !*cmd ) {
6188                 return WERR_ACCESS_DENIED;
6189         }
6190
6191         command = talloc_asprintf(ctx,
6192                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6193         if (!command) {
6194                 return WERR_NOMEM;
6195         }
6196
6197         if ( token )
6198                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6199
6200         DEBUG(10,("Running [%s]\n", command));
6201
6202         /********* BEGIN SePrintOperatorPrivilege **********/
6203
6204         if ( is_print_op )
6205                 become_root();
6206
6207         ret = smbrun(command, NULL);
6208
6209         if ( is_print_op )
6210                 unbecome_root();
6211
6212         /********* END SePrintOperatorPrivilege **********/
6213
6214         DEBUGADD(10,("returned [%d]\n", ret));
6215
6216         TALLOC_FREE(command);
6217
6218         if ( ret != 0 ) {
6219                 return WERR_ACCESS_DENIED;
6220         }
6221
6222         return WERR_OK;
6223 }
6224
6225 /****************************************************************************
6226 ****************************************************************************/
6227
6228 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6229                                    int snum)
6230 {
6231         /*
6232          * As we do not know if we are embedded in the file server process
6233          * or not, we have to pretend that all shares are in use.
6234          */
6235         return true;
6236 }
6237
6238 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6239                              struct spoolss_SetPrinterInfo2 *info2,
6240                              const char *remote_machine,
6241                              struct messaging_context *msg_ctx)
6242 {
6243         char *cmd = lp_addprinter_cmd(talloc_tos());
6244         char **qlines;
6245         char *command = NULL;
6246         int numlines;
6247         int ret;
6248         int fd;
6249         bool is_print_op = false;
6250
6251         if (!remote_machine) {
6252                 return false;
6253         }
6254
6255         command = talloc_asprintf(ctx,
6256                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6257                         cmd, info2->printername, info2->sharename,
6258                         info2->portname, info2->drivername,
6259                         info2->location, info2->comment, remote_machine);
6260         if (!command) {
6261                 return false;
6262         }
6263
6264         if ( token )
6265                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6266
6267         DEBUG(10,("Running [%s]\n", command));
6268
6269         /********* BEGIN SePrintOperatorPrivilege **********/
6270
6271         if ( is_print_op )
6272                 become_root();
6273
6274         if ( (ret = smbrun(command, &fd)) == 0 ) {
6275                 /* Tell everyone we updated smb.conf. */
6276                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6277         }
6278
6279         if ( is_print_op )
6280                 unbecome_root();
6281
6282         /********* END SePrintOperatorPrivilege **********/
6283
6284         DEBUGADD(10,("returned [%d]\n", ret));
6285
6286         TALLOC_FREE(command);
6287
6288         if ( ret != 0 ) {
6289                 if (fd != -1)
6290                         close(fd);
6291                 return false;
6292         }
6293
6294         /* reload our services immediately */
6295         become_root();
6296         reload_services(NULL, spoolss_conn_snum_used, false);
6297         unbecome_root();
6298
6299         numlines = 0;
6300         /* Get lines and convert them back to dos-codepage */
6301         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6302         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6303         close(fd);
6304
6305         /* Set the portname to what the script says the portname should be. */
6306         /* but don't require anything to be return from the script exit a good error code */
6307
6308         if (numlines) {
6309                 /* Set the portname to what the script says the portname should be. */
6310                 info2->portname = talloc_strdup(ctx, qlines[0]);
6311                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6312         }
6313
6314         TALLOC_FREE(qlines);
6315         return true;
6316 }
6317
6318 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6319                                const struct auth_session_info *session_info,
6320                                struct messaging_context *msg_ctx,
6321                                int snum,
6322                                struct spoolss_SetPrinterInfo2 *printer,
6323                                struct spoolss_PrinterInfo2 *old_printer)
6324 {
6325         bool force_update = (old_printer == NULL);
6326         const char *dnsdomname;
6327         const char *longname;
6328         const char *uncname;
6329         const char *spooling;
6330         DATA_BLOB buffer;
6331         WERROR result = WERR_OK;
6332         struct dcerpc_binding_handle *b;
6333         TALLOC_CTX *tmp_ctx;
6334         bool ok;
6335
6336         tmp_ctx = talloc_new(mem_ctx);
6337         if (!tmp_ctx) {
6338                 return WERR_NOMEM;
6339         }
6340
6341         result = winreg_printer_binding_handle(tmp_ctx,
6342                                                session_info,
6343                                                msg_ctx,
6344                                                &b);
6345         if (!W_ERROR_IS_OK(result)) {
6346                 goto done;
6347         }
6348
6349         if (printer->drivername != NULL &&
6350             (force_update ||
6351              !strequal(printer->drivername, old_printer->drivername))) {
6352                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6353                 if (!ok) {
6354                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6355                         result = WERR_INVALID_DATA;
6356                         goto done;
6357                 }
6358                 result = winreg_set_printer_dataex(tmp_ctx, b,
6359                                           printer->sharename,
6360                                           SPOOL_DSSPOOLER_KEY,
6361                                           SPOOL_REG_DRIVERNAME,
6362                                           REG_SZ,
6363                                           buffer.data,
6364                                           buffer.length);
6365                 if (!W_ERROR_IS_OK(result)) {
6366                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6367                         goto done;
6368                 }
6369
6370                 if (!force_update) {
6371                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6372                                 printer->drivername));
6373
6374                         notify_printer_driver(server_event_context(), msg_ctx,
6375                                               snum, printer->drivername ?
6376                                               printer->drivername : "");
6377                 }
6378         }
6379
6380         if (printer->comment != NULL &&
6381             (force_update ||
6382              !strequal(printer->comment, old_printer->comment))) {
6383                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6384                 if (!ok) {
6385                         DEBUG(0, ("comment data corrupted\n"));
6386                         result = WERR_INVALID_DATA;
6387                         goto done;
6388                 }
6389                 result = winreg_set_printer_dataex(tmp_ctx, b,
6390                                           printer->sharename,
6391                                           SPOOL_DSSPOOLER_KEY,
6392                                           SPOOL_REG_DESCRIPTION,
6393                                           REG_SZ,
6394                                           buffer.data,
6395                                           buffer.length);
6396                 if (!W_ERROR_IS_OK(result)) {
6397                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6398                         goto done;
6399                 }
6400
6401                 if (!force_update) {
6402                         notify_printer_comment(server_event_context(), msg_ctx,
6403                                                snum, printer->comment ?
6404                                                printer->comment : "");
6405                 }
6406         }
6407
6408         if (printer->sharename != NULL &&
6409             (force_update ||
6410              !strequal(printer->sharename, old_printer->sharename))) {
6411                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6412                 if (!ok) {
6413                         DEBUG(0, ("sharename data corrupted\n"));
6414                         result = WERR_INVALID_DATA;
6415                         goto done;
6416                 }
6417                 result = winreg_set_printer_dataex(tmp_ctx, b,
6418                                           printer->sharename,
6419                                           SPOOL_DSSPOOLER_KEY,
6420                                           SPOOL_REG_PRINTSHARENAME,
6421                                           REG_SZ,
6422                                           buffer.data,
6423                                           buffer.length);
6424                 if (!W_ERROR_IS_OK(result)) {
6425                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6426                         goto done;
6427                 }
6428
6429                 if (!force_update) {
6430                         notify_printer_sharename(server_event_context(),
6431                                                  msg_ctx,
6432                                                  snum, printer->sharename ?
6433                                                  printer->sharename : "");
6434                 }
6435         }
6436
6437         if (printer->printername != NULL &&
6438             (force_update ||
6439              !strequal(printer->printername, old_printer->printername))) {
6440                 const char *p;
6441
6442                 p = strrchr(printer->printername, '\\' );
6443                 if (p != NULL) {
6444                         p++;
6445                 } else {
6446                         p = printer->printername;
6447                 }
6448
6449                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6450                 if (!ok) {
6451                         DEBUG(0, ("printername data corrupted\n"));
6452                         result = WERR_INVALID_DATA;
6453                         goto done;
6454                 }
6455                 result = winreg_set_printer_dataex(tmp_ctx, b,
6456                                           printer->sharename,
6457                                           SPOOL_DSSPOOLER_KEY,
6458                                           SPOOL_REG_PRINTERNAME,
6459                                           REG_SZ,
6460                                           buffer.data,
6461                                           buffer.length);
6462                 if (!W_ERROR_IS_OK(result)) {
6463                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6464                         goto done;
6465                 }
6466
6467                 if (!force_update) {
6468                         notify_printer_printername(server_event_context(),
6469                                                    msg_ctx, snum, p ? p : "");
6470                 }
6471         }
6472
6473         if (printer->portname != NULL &&
6474             (force_update ||
6475              !strequal(printer->portname, old_printer->portname))) {
6476                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6477                 if (!ok) {
6478                         DEBUG(0, ("portname data corrupted\n"));
6479                         result = WERR_INVALID_DATA;
6480                         goto done;
6481                 }
6482                 result = winreg_set_printer_dataex(tmp_ctx, b,
6483                                           printer->sharename,
6484                                           SPOOL_DSSPOOLER_KEY,
6485                                           SPOOL_REG_PORTNAME,
6486                                           REG_SZ,
6487                                           buffer.data,
6488                                           buffer.length);
6489                 if (!W_ERROR_IS_OK(result)) {
6490                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6491                         goto done;
6492                 }
6493
6494                 if (!force_update) {
6495                         notify_printer_port(server_event_context(),
6496                                             msg_ctx, snum, printer->portname ?
6497                                             printer->portname : "");
6498                 }
6499         }
6500
6501         if (printer->location != NULL &&
6502             (force_update ||
6503              !strequal(printer->location, old_printer->location))) {
6504                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6505                 if (!ok) {
6506                         DEBUG(0, ("location data corrupted\n"));
6507                         result = WERR_INVALID_DATA;
6508                         goto done;
6509                 }
6510                 result = winreg_set_printer_dataex(tmp_ctx, b,
6511                                           printer->sharename,
6512                                           SPOOL_DSSPOOLER_KEY,
6513                                           SPOOL_REG_LOCATION,
6514                                           REG_SZ,
6515                                           buffer.data,
6516                                           buffer.length);
6517                 if (!W_ERROR_IS_OK(result)) {
6518                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6519                         goto done;
6520                 }
6521
6522                 if (!force_update) {
6523                         notify_printer_location(server_event_context(),
6524                                                 msg_ctx, snum,
6525                                                 printer->location ?
6526                                                 printer->location : "");
6527                 }
6528         }
6529
6530         if (printer->sepfile != NULL &&
6531             (force_update ||
6532              !strequal(printer->sepfile, old_printer->sepfile))) {
6533                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6534                 if (!ok) {
6535                         DEBUG(0, ("sepfile data corrupted\n"));
6536                         result = WERR_INVALID_DATA;
6537                         goto done;
6538                 }
6539                 result = winreg_set_printer_dataex(tmp_ctx, b,
6540                                           printer->sharename,
6541                                           SPOOL_DSSPOOLER_KEY,
6542                                           SPOOL_REG_PRINTSEPARATORFILE,
6543                                           REG_SZ,
6544                                           buffer.data,
6545                                           buffer.length);
6546                 if (!W_ERROR_IS_OK(result)) {
6547                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6548                         goto done;
6549                 }
6550
6551                 if (!force_update) {
6552                         notify_printer_sepfile(server_event_context(),
6553                                                msg_ctx, snum,
6554                                                printer->sepfile ?
6555                                                printer->sepfile : "");
6556                 }
6557         }
6558
6559         if (printer->starttime != 0 &&
6560             (force_update ||
6561              printer->starttime != old_printer->starttime)) {
6562                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6563                 SIVAL(buffer.data, 0, printer->starttime);
6564                 result = winreg_set_printer_dataex(tmp_ctx, b,
6565                                           printer->sharename,
6566                                           SPOOL_DSSPOOLER_KEY,
6567                                           SPOOL_REG_PRINTSTARTTIME,
6568                                           REG_DWORD,
6569                                           buffer.data,
6570                                           buffer.length);
6571                 if (!W_ERROR_IS_OK(result)) {
6572                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6573                         goto done;
6574                 }
6575         }
6576
6577         if (printer->untiltime != 0 &&
6578             (force_update ||
6579              printer->untiltime != old_printer->untiltime)) {
6580                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6581                 SIVAL(buffer.data, 0, printer->untiltime);
6582                 result = winreg_set_printer_dataex(tmp_ctx, b,
6583                                           printer->sharename,
6584                                           SPOOL_DSSPOOLER_KEY,
6585                                           SPOOL_REG_PRINTENDTIME,
6586                                           REG_DWORD,
6587                                           buffer.data,
6588                                           buffer.length);
6589                 if (!W_ERROR_IS_OK(result)) {
6590                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6591                         goto done;
6592                 }
6593         }
6594
6595         if (force_update || printer->priority != old_printer->priority) {
6596                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6597                 SIVAL(buffer.data, 0, printer->priority);
6598                 result = winreg_set_printer_dataex(tmp_ctx, b,
6599                                           printer->sharename,
6600                                           SPOOL_DSSPOOLER_KEY,
6601                                           SPOOL_REG_PRIORITY,
6602                                           REG_DWORD,
6603                                           buffer.data,
6604                                           buffer.length);
6605                 if (!W_ERROR_IS_OK(result)) {
6606                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6607                         goto done;
6608                 }
6609         }
6610
6611         if (force_update || printer->attributes != old_printer->attributes) {
6612                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6613                 SIVAL(buffer.data, 0, (printer->attributes &
6614                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6615                 result = winreg_set_printer_dataex(tmp_ctx, b,
6616                                           printer->sharename,
6617                                           SPOOL_DSSPOOLER_KEY,
6618                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6619                                           REG_DWORD,
6620                                           buffer.data,
6621                                           buffer.length);
6622                 if (!W_ERROR_IS_OK(result)) {
6623                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6624                         goto done;
6625                 }
6626
6627                 switch (printer->attributes & 0x3) {
6628                         case 0:
6629                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6630                                 break;
6631                         case 1:
6632                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6633                                 break;
6634                         case 2:
6635                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6636                                 break;
6637                         default:
6638                                 spooling = "unknown";
6639                 }
6640                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6641                 if (!ok) {
6642                         DEBUG(0, ("printSpooling data corrupted\n"));
6643                         result = WERR_INVALID_DATA;
6644                         goto done;
6645                 }
6646                 winreg_set_printer_dataex(tmp_ctx, b,
6647                                           printer->sharename,
6648                                           SPOOL_DSSPOOLER_KEY,
6649                                           SPOOL_REG_PRINTSPOOLING,
6650                                           REG_SZ,
6651                                           buffer.data,
6652                                           buffer.length);
6653         }
6654
6655         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6656         if (!ok) {
6657                 DEBUG(0, ("shortServerName data corrupted\n"));
6658                 result = WERR_INVALID_DATA;
6659                 goto done;
6660         }
6661         result = winreg_set_printer_dataex(tmp_ctx, b,
6662                                   printer->sharename,
6663                                   SPOOL_DSSPOOLER_KEY,
6664                                   SPOOL_REG_SHORTSERVERNAME,
6665                                   REG_SZ,
6666                                   buffer.data,
6667                                   buffer.length);
6668         if (!W_ERROR_IS_OK(result)) {
6669                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6670                 goto done;
6671         }
6672
6673         dnsdomname = get_mydnsfullname();
6674         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6675                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6676         } else {
6677                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6678         }
6679         if (longname == NULL) {
6680                 result = WERR_NOMEM;
6681                 goto done;
6682         }
6683
6684         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6685         if (!ok) {
6686                 DEBUG(0, ("longname data corrupted\n"));
6687                 result = WERR_INVALID_DATA;
6688                 goto done;
6689         }
6690         result = winreg_set_printer_dataex(tmp_ctx, b,
6691                                            printer->sharename,
6692                                            SPOOL_DSSPOOLER_KEY,
6693                                            SPOOL_REG_SERVERNAME,
6694                                            REG_SZ,
6695                                            buffer.data,
6696                                            buffer.length);
6697         if (!W_ERROR_IS_OK(result)) {
6698                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6699                 goto done;
6700         }
6701
6702         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6703                                   lp_netbios_name(), printer->sharename);
6704         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6705         if (!ok) {
6706                 DEBUG(0, ("uncName data corrupted\n"));
6707                 result = WERR_INVALID_DATA;
6708                 goto done;
6709         }
6710         result = winreg_set_printer_dataex(tmp_ctx, b,
6711                                   printer->sharename,
6712                                   SPOOL_DSSPOOLER_KEY,
6713                                   SPOOL_REG_UNCNAME,
6714                                   REG_SZ,
6715                                   buffer.data,
6716                                   buffer.length);
6717         if (!W_ERROR_IS_OK(result)) {
6718                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6719                 goto done;
6720         }
6721
6722 done:
6723         talloc_free(tmp_ctx);
6724         return result;
6725 }
6726
6727 /********************************************************************
6728  * Called by spoolss_api_setprinter
6729  * when updating a printer description.
6730  ********************************************************************/
6731
6732 static WERROR update_printer(struct pipes_struct *p,
6733                              struct policy_handle *handle,
6734                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6735                              struct spoolss_DeviceMode *devmode)
6736 {
6737         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6738         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6739         struct spoolss_PrinterInfo2 *old_printer;
6740         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6741         int snum;
6742         WERROR result = WERR_OK;
6743         TALLOC_CTX *tmp_ctx;
6744         struct dcerpc_binding_handle *b;
6745
6746         DEBUG(8,("update_printer\n"));
6747
6748         tmp_ctx = talloc_new(p->mem_ctx);
6749         if (tmp_ctx == NULL) {
6750                 return WERR_NOMEM;
6751         }
6752
6753         if (!Printer) {
6754                 result = WERR_BADFID;
6755                 goto done;
6756         }
6757
6758         if (!get_printer_snum(p, handle, &snum, NULL)) {
6759                 result = WERR_BADFID;
6760                 goto done;
6761         }
6762
6763         result = winreg_printer_binding_handle(tmp_ctx,
6764                                                get_session_info_system(),
6765                                                p->msg_ctx,
6766                                                &b);
6767         if (!W_ERROR_IS_OK(result)) {
6768                 goto done;
6769         }
6770
6771         result = winreg_get_printer(tmp_ctx, b,
6772                                     lp_const_servicename(snum),
6773                                     &old_printer);
6774         if (!W_ERROR_IS_OK(result)) {
6775                 result = WERR_BADFID;
6776                 goto done;
6777         }
6778
6779         /* Do sanity check on the requested changes for Samba */
6780         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6781                 result = WERR_INVALID_PARAM;
6782                 goto done;
6783         }
6784
6785         /* FIXME!!! If the driver has changed we really should verify that
6786            it is installed before doing much else   --jerry */
6787
6788         /* Check calling user has permission to update printer description */
6789         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6790                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6791                 result = WERR_ACCESS_DENIED;
6792                 goto done;
6793         }
6794
6795         /* Call addprinter hook */
6796         /* Check changes to see if this is really needed */
6797
6798         if (*lp_addprinter_cmd(talloc_tos()) &&
6799                         (!strequal(printer->drivername, old_printer->drivername) ||
6800                          !strequal(printer->comment, old_printer->comment) ||
6801                          !strequal(printer->portname, old_printer->portname) ||
6802                          !strequal(printer->location, old_printer->location)) )
6803         {
6804                 char *raddr;
6805
6806                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6807                                                          p->mem_ctx);
6808                 if (raddr == NULL) {
6809                         return WERR_NOMEM;
6810                 }
6811
6812                 /* add_printer_hook() will call reload_services() */
6813                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6814                                       printer, raddr,
6815                                       p->msg_ctx)) {
6816                         result = WERR_ACCESS_DENIED;
6817                         goto done;
6818                 }
6819         }
6820
6821         result = update_dsspooler(tmp_ctx,
6822                                   get_session_info_system(),
6823                                   p->msg_ctx,
6824                                   snum,
6825                                   printer,
6826                                   old_printer);
6827         if (!W_ERROR_IS_OK(result)) {
6828                 goto done;
6829         }
6830
6831         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6832
6833         if (devmode == NULL) {
6834                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6835         }
6836         result = winreg_update_printer(tmp_ctx, b,
6837                                        printer->sharename,
6838                                        printer_mask,
6839                                        printer,
6840                                        devmode,
6841                                        NULL);
6842
6843 done:
6844         talloc_free(tmp_ctx);
6845
6846         return result;
6847 }
6848
6849 /****************************************************************************
6850 ****************************************************************************/
6851 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6852                                            struct policy_handle *handle,
6853                                            struct spoolss_SetPrinterInfo7 *info7)
6854 {
6855 #ifdef HAVE_ADS
6856         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6857         WERROR result;
6858         int snum;
6859         struct printer_handle *Printer;
6860
6861         if ( lp_security() != SEC_ADS ) {
6862                 return WERR_UNKNOWN_LEVEL;
6863         }
6864
6865         Printer = find_printer_index_by_hnd(p, handle);
6866
6867         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6868
6869         if (!Printer)
6870                 return WERR_BADFID;
6871
6872         if (!get_printer_snum(p, handle, &snum, NULL))
6873                 return WERR_BADFID;
6874
6875         result = winreg_get_printer_internal(p->mem_ctx,
6876                                     get_session_info_system(),
6877                                     p->msg_ctx,
6878                                     lp_servicename(talloc_tos(), snum),
6879                                     &pinfo2);
6880         if (!W_ERROR_IS_OK(result)) {
6881                 return WERR_BADFID;
6882         }
6883
6884         nt_printer_publish(pinfo2,
6885                            get_session_info_system(),
6886                            p->msg_ctx,
6887                            pinfo2,
6888                            info7->action);
6889
6890         TALLOC_FREE(pinfo2);
6891         return WERR_OK;
6892 #else
6893         return WERR_UNKNOWN_LEVEL;
6894 #endif
6895 }
6896
6897 /********************************************************************
6898  ********************************************************************/
6899
6900 static WERROR update_printer_devmode(struct pipes_struct *p,
6901                                      struct policy_handle *handle,
6902                                      struct spoolss_DeviceMode *devmode)
6903 {
6904         int snum;
6905         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6906         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6907
6908         DEBUG(8,("update_printer_devmode\n"));
6909
6910         if (!Printer) {
6911                 return WERR_BADFID;
6912         }
6913
6914         if (!get_printer_snum(p, handle, &snum, NULL)) {
6915                 return WERR_BADFID;
6916         }
6917
6918         /* Check calling user has permission to update printer description */
6919         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6920                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6921                 return WERR_ACCESS_DENIED;
6922         }
6923
6924         return winreg_update_printer_internal(p->mem_ctx,
6925                                      get_session_info_system(),
6926                                      p->msg_ctx,
6927                                      lp_const_servicename(snum),
6928                                      info2_mask,
6929                                      NULL,
6930                                      devmode,
6931                                      NULL);
6932 }
6933
6934
6935 /****************************************************************
6936  _spoolss_SetPrinter
6937 ****************************************************************/
6938
6939 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6940                            struct spoolss_SetPrinter *r)
6941 {
6942         WERROR result;
6943
6944         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6945
6946         if (!Printer) {
6947                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6948                         OUR_HANDLE(r->in.handle)));
6949                 return WERR_BADFID;
6950         }
6951
6952         /* check the level */
6953         switch (r->in.info_ctr->level) {
6954                 case 0:
6955                         return control_printer(r->in.handle, r->in.command, p);
6956                 case 2:
6957                         result = update_printer(p, r->in.handle,
6958                                                 r->in.info_ctr,
6959                                                 r->in.devmode_ctr->devmode);
6960                         if (!W_ERROR_IS_OK(result))
6961                                 return result;
6962                         if (r->in.secdesc_ctr->sd)
6963                                 result = update_printer_sec(r->in.handle, p,
6964                                                             r->in.secdesc_ctr);
6965                         return result;
6966                 case 3:
6967                         return update_printer_sec(r->in.handle, p,
6968                                                   r->in.secdesc_ctr);
6969                 case 7:
6970                         return publish_or_unpublish_printer(p, r->in.handle,
6971                                                             r->in.info_ctr->info.info7);
6972                 case 8:
6973                         return update_printer_devmode(p, r->in.handle,
6974                                                       r->in.devmode_ctr->devmode);
6975                 default:
6976                         return WERR_UNKNOWN_LEVEL;
6977         }
6978 }
6979
6980 /****************************************************************
6981  _spoolss_FindClosePrinterNotify
6982 ****************************************************************/
6983
6984 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6985                                        struct spoolss_FindClosePrinterNotify *r)
6986 {
6987         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6988
6989         if (!Printer) {
6990                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6991                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6992                 return WERR_BADFID;
6993         }
6994
6995         if (Printer->notify.cli_chan != NULL &&
6996             Printer->notify.cli_chan->active_connections > 0) {
6997                 int snum = -1;
6998
6999                 if (Printer->printer_type == SPLHND_PRINTER) {
7000                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7001                                 return WERR_BADFID;
7002                         }
7003                 }
7004
7005                 srv_spoolss_replycloseprinter(snum, Printer);
7006         }
7007
7008         Printer->notify.flags=0;
7009         Printer->notify.options=0;
7010         Printer->notify.localmachine[0]='\0';
7011         Printer->notify.printerlocal=0;
7012         TALLOC_FREE(Printer->notify.option);
7013
7014         return WERR_OK;
7015 }
7016
7017 /****************************************************************
7018  _spoolss_AddJob
7019 ****************************************************************/
7020
7021 WERROR _spoolss_AddJob(struct pipes_struct *p,
7022                        struct spoolss_AddJob *r)
7023 {
7024         if (!r->in.buffer && (r->in.offered != 0)) {
7025                 return WERR_INVALID_PARAM;
7026         }
7027
7028         /* this is what a NT server returns for AddJob. AddJob must fail on
7029          * non-local printers */
7030
7031         if (r->in.level != 1) {
7032                 return WERR_UNKNOWN_LEVEL;
7033         }
7034
7035         return WERR_INVALID_PARAM;
7036 }
7037
7038 /****************************************************************************
7039 fill_job_info1
7040 ****************************************************************************/
7041
7042 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7043                              struct spoolss_JobInfo1 *r,
7044                              const print_queue_struct *queue,
7045                              int position, int snum,
7046                              struct spoolss_PrinterInfo2 *pinfo2)
7047 {
7048         struct tm *t;
7049
7050         t = gmtime(&queue->time);
7051
7052         r->job_id               = queue->sysjob;
7053
7054         r->printer_name         = lp_servicename(mem_ctx, snum);
7055         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7056         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7057         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7058         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7059         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7060         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7061         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7062         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7063         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7064         r->text_status          = talloc_strdup(mem_ctx, "");
7065         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7066
7067         r->status               = nt_printj_status(queue->status);
7068         r->priority             = queue->priority;
7069         r->position             = position;
7070         r->total_pages          = queue->page_count;
7071         r->pages_printed        = 0; /* ??? */
7072
7073         init_systemtime(&r->submitted, t);
7074
7075         return WERR_OK;
7076 }
7077
7078 /****************************************************************************
7079 fill_job_info2
7080 ****************************************************************************/
7081
7082 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7083                              struct spoolss_JobInfo2 *r,
7084                              const print_queue_struct *queue,
7085                              int position, int snum,
7086                              struct spoolss_PrinterInfo2 *pinfo2,
7087                              struct spoolss_DeviceMode *devmode)
7088 {
7089         struct tm *t;
7090
7091         t = gmtime(&queue->time);
7092
7093         r->job_id               = queue->sysjob;
7094
7095         r->printer_name         = lp_servicename(mem_ctx, snum);
7096         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7097         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7098         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7099         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7100         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7101         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7102         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7103         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7104         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7105         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7106         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7107         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7108         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7109         r->parameters           = talloc_strdup(mem_ctx, "");
7110         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7111         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7112         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7113
7114         r->devmode              = devmode;
7115
7116         r->text_status          = talloc_strdup(mem_ctx, "");
7117         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7118
7119         r->secdesc              = NULL;
7120
7121         r->status               = nt_printj_status(queue->status);
7122         r->priority             = queue->priority;
7123         r->position             = position;
7124         r->start_time           = 0;
7125         r->until_time           = 0;
7126         r->total_pages          = queue->page_count;
7127         r->size                 = queue->size;
7128         init_systemtime(&r->submitted, t);
7129         r->time                 = 0;
7130         r->pages_printed        = 0; /* ??? */
7131
7132         return WERR_OK;
7133 }
7134
7135 /****************************************************************************
7136 fill_job_info3
7137 ****************************************************************************/
7138
7139 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7140                              struct spoolss_JobInfo3 *r,
7141                              const print_queue_struct *queue,
7142                              const print_queue_struct *next_queue,
7143                              int position, int snum,
7144                              struct spoolss_PrinterInfo2 *pinfo2)
7145 {
7146         r->job_id               = queue->sysjob;
7147         r->next_job_id          = 0;
7148         if (next_queue) {
7149                 r->next_job_id  = next_queue->sysjob;
7150         }
7151         r->reserved             = 0;
7152
7153         return WERR_OK;
7154 }
7155
7156 /****************************************************************************
7157  Enumjobs at level 1.
7158 ****************************************************************************/
7159
7160 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7161                               const print_queue_struct *queue,
7162                               uint32_t num_queues, int snum,
7163                               struct spoolss_PrinterInfo2 *pinfo2,
7164                               union spoolss_JobInfo **info_p,
7165                               uint32_t *count)
7166 {
7167         union spoolss_JobInfo *info;
7168         int i;
7169         WERROR result = WERR_OK;
7170
7171         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7172         W_ERROR_HAVE_NO_MEMORY(info);
7173
7174         *count = num_queues;
7175
7176         for (i=0; i<*count; i++) {
7177                 result = fill_job_info1(info,
7178                                         &info[i].info1,
7179                                         &queue[i],
7180                                         i,
7181                                         snum,
7182                                         pinfo2);
7183                 if (!W_ERROR_IS_OK(result)) {
7184                         goto out;
7185                 }
7186         }
7187
7188  out:
7189         if (!W_ERROR_IS_OK(result)) {
7190                 TALLOC_FREE(info);
7191                 *count = 0;
7192                 return result;
7193         }
7194
7195         *info_p = info;
7196
7197         return WERR_OK;
7198 }
7199
7200 /****************************************************************************
7201  Enumjobs at level 2.
7202 ****************************************************************************/
7203
7204 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7205                               const print_queue_struct *queue,
7206                               uint32_t num_queues, int snum,
7207                               struct spoolss_PrinterInfo2 *pinfo2,
7208                               union spoolss_JobInfo **info_p,
7209                               uint32_t *count)
7210 {
7211         union spoolss_JobInfo *info;
7212         int i;
7213         WERROR result = WERR_OK;
7214
7215         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7216         W_ERROR_HAVE_NO_MEMORY(info);
7217
7218         *count = num_queues;
7219
7220         for (i=0; i<*count; i++) {
7221                 struct spoolss_DeviceMode *devmode;
7222
7223                 result = spoolss_create_default_devmode(info,
7224                                                         pinfo2->printername,
7225                                                         &devmode);
7226                 if (!W_ERROR_IS_OK(result)) {
7227                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7228                         goto out;
7229                 }
7230
7231                 result = fill_job_info2(info,
7232                                         &info[i].info2,
7233                                         &queue[i],
7234                                         i,
7235                                         snum,
7236                                         pinfo2,
7237                                         devmode);
7238                 if (!W_ERROR_IS_OK(result)) {
7239                         goto out;
7240                 }
7241         }
7242
7243  out:
7244         if (!W_ERROR_IS_OK(result)) {
7245                 TALLOC_FREE(info);
7246                 *count = 0;
7247                 return result;
7248         }
7249
7250         *info_p = info;
7251
7252         return WERR_OK;
7253 }
7254
7255 /****************************************************************************
7256  Enumjobs at level 3.
7257 ****************************************************************************/
7258
7259 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7260                               const print_queue_struct *queue,
7261                               uint32_t num_queues, int snum,
7262                               struct spoolss_PrinterInfo2 *pinfo2,
7263                               union spoolss_JobInfo **info_p,
7264                               uint32_t *count)
7265 {
7266         union spoolss_JobInfo *info;
7267         int i;
7268         WERROR result = WERR_OK;
7269
7270         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7271         W_ERROR_HAVE_NO_MEMORY(info);
7272
7273         *count = num_queues;
7274
7275         for (i=0; i<*count; i++) {
7276                 const print_queue_struct *next_queue = NULL;
7277
7278                 if (i+1 < *count) {
7279                         next_queue = &queue[i+1];
7280                 }
7281
7282                 result = fill_job_info3(info,
7283                                         &info[i].info3,
7284                                         &queue[i],
7285                                         next_queue,
7286                                         i,
7287                                         snum,
7288                                         pinfo2);
7289                 if (!W_ERROR_IS_OK(result)) {
7290                         goto out;
7291                 }
7292         }
7293
7294  out:
7295         if (!W_ERROR_IS_OK(result)) {
7296                 TALLOC_FREE(info);
7297                 *count = 0;
7298                 return result;
7299         }
7300
7301         *info_p = info;
7302
7303         return WERR_OK;
7304 }
7305
7306 /****************************************************************
7307  _spoolss_EnumJobs
7308 ****************************************************************/
7309
7310 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7311                          struct spoolss_EnumJobs *r)
7312 {
7313         WERROR result;
7314         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7315         int snum;
7316         print_status_struct prt_status;
7317         print_queue_struct *queue = NULL;
7318         uint32_t count;
7319
7320         /* that's an [in out] buffer */
7321
7322         if (!r->in.buffer && (r->in.offered != 0)) {
7323                 return WERR_INVALID_PARAM;
7324         }
7325
7326         DEBUG(4,("_spoolss_EnumJobs\n"));
7327
7328         *r->out.needed = 0;
7329         *r->out.count = 0;
7330         *r->out.info = NULL;
7331
7332         /* lookup the printer snum and tdb entry */
7333
7334         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7335                 return WERR_BADFID;
7336         }
7337
7338         result = winreg_get_printer_internal(p->mem_ctx,
7339                                     get_session_info_system(),
7340                                     p->msg_ctx,
7341                                     lp_const_servicename(snum),
7342                                     &pinfo2);
7343         if (!W_ERROR_IS_OK(result)) {
7344                 return result;
7345         }
7346
7347         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7348         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7349                 count, prt_status.status, prt_status.message));
7350
7351         if (count == 0) {
7352                 SAFE_FREE(queue);
7353                 TALLOC_FREE(pinfo2);
7354                 return WERR_OK;
7355         }
7356
7357         switch (r->in.level) {
7358         case 1:
7359                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7360                                          pinfo2, r->out.info, r->out.count);
7361                 break;
7362         case 2:
7363                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7364                                          pinfo2, r->out.info, r->out.count);
7365                 break;
7366         case 3:
7367                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7368                                          pinfo2, r->out.info, r->out.count);
7369                 break;
7370         default:
7371                 result = WERR_UNKNOWN_LEVEL;
7372                 break;
7373         }
7374
7375         SAFE_FREE(queue);
7376         TALLOC_FREE(pinfo2);
7377
7378         if (!W_ERROR_IS_OK(result)) {
7379                 return result;
7380         }
7381
7382         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7383                                                      spoolss_EnumJobs,
7384                                                      *r->out.info, r->in.level,
7385                                                      *r->out.count);
7386         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7387         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7388
7389         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7390 }
7391
7392 /****************************************************************
7393  _spoolss_ScheduleJob
7394 ****************************************************************/
7395
7396 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7397                             struct spoolss_ScheduleJob *r)
7398 {
7399         return WERR_OK;
7400 }
7401
7402 /****************************************************************
7403 ****************************************************************/
7404
7405 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7406                                struct messaging_context *msg_ctx,
7407                                const char *printer_name,
7408                                uint32_t job_id,
7409                                struct spoolss_SetJobInfo1 *r)
7410 {
7411         char *old_doc_name;
7412
7413         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7414                 return WERR_BADFID;
7415         }
7416
7417         if (strequal(old_doc_name, r->document_name)) {
7418                 return WERR_OK;
7419         }
7420
7421         if (!print_job_set_name(server_event_context(), msg_ctx,
7422                                 printer_name, job_id, r->document_name)) {
7423                 return WERR_BADFID;
7424         }
7425
7426         return WERR_OK;
7427 }
7428
7429 /****************************************************************
7430  _spoolss_SetJob
7431 ****************************************************************/
7432
7433 WERROR _spoolss_SetJob(struct pipes_struct *p,
7434                        struct spoolss_SetJob *r)
7435 {
7436         const struct auth_session_info *session_info = p->session_info;
7437         int snum;
7438         WERROR errcode = WERR_BADFUNC;
7439
7440         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7441                 return WERR_BADFID;
7442         }
7443
7444         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7445                 return WERR_INVALID_PRINTER_NAME;
7446         }
7447
7448         switch (r->in.command) {
7449         case SPOOLSS_JOB_CONTROL_CANCEL:
7450         case SPOOLSS_JOB_CONTROL_DELETE:
7451                 errcode = print_job_delete(session_info, p->msg_ctx,
7452                                            snum, r->in.job_id);
7453                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7454                         errcode = WERR_OK;
7455                 }
7456                 break;
7457         case SPOOLSS_JOB_CONTROL_PAUSE:
7458                 errcode = print_job_pause(session_info, p->msg_ctx,
7459                                           snum, r->in.job_id);
7460                 break;
7461         case SPOOLSS_JOB_CONTROL_RESTART:
7462         case SPOOLSS_JOB_CONTROL_RESUME:
7463                 errcode = print_job_resume(session_info, p->msg_ctx,
7464                                            snum, r->in.job_id);
7465                 break;
7466         case 0:
7467                 errcode = WERR_OK;
7468                 break;
7469         default:
7470                 return WERR_UNKNOWN_LEVEL;
7471         }
7472
7473         if (!W_ERROR_IS_OK(errcode)) {
7474                 return errcode;
7475         }
7476
7477         if (r->in.ctr == NULL) {
7478                 return errcode;
7479         }
7480
7481         switch (r->in.ctr->level) {
7482         case 1:
7483                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7484                                            lp_const_servicename(snum),
7485                                            r->in.job_id,
7486                                            r->in.ctr->info.info1);
7487                 break;
7488         case 2:
7489         case 3:
7490         case 4:
7491         default:
7492                 return WERR_UNKNOWN_LEVEL;
7493         }
7494
7495         return errcode;
7496 }
7497
7498 /****************************************************************************
7499  Enumerates all printer drivers by level and architecture.
7500 ****************************************************************************/
7501
7502 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7503                                                        const struct auth_session_info *session_info,
7504                                                        struct messaging_context *msg_ctx,
7505                                                        const char *servername,
7506                                                        const char *architecture,
7507                                                        uint32_t level,
7508                                                        union spoolss_DriverInfo **info_p,
7509                                                        uint32_t *count_p)
7510 {
7511         int i;
7512         uint32_t version;
7513         struct spoolss_DriverInfo8 *driver;
7514         union spoolss_DriverInfo *info = NULL;
7515         uint32_t count = 0;
7516         WERROR result = WERR_OK;
7517         uint32_t num_drivers;
7518         const char **drivers;
7519         struct dcerpc_binding_handle *b;
7520         TALLOC_CTX *tmp_ctx = NULL;
7521
7522         *count_p = 0;
7523         *info_p = NULL;
7524
7525         tmp_ctx = talloc_new(mem_ctx);
7526         if (!tmp_ctx) {
7527                 return WERR_NOMEM;
7528         }
7529
7530         result = winreg_printer_binding_handle(tmp_ctx,
7531                                                session_info,
7532                                                msg_ctx,
7533                                                &b);
7534         if (!W_ERROR_IS_OK(result)) {
7535                 goto out;
7536         }
7537
7538         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7539                 result = winreg_get_driver_list(tmp_ctx, b,
7540                                                 architecture, version,
7541                                                 &num_drivers, &drivers);
7542                 if (!W_ERROR_IS_OK(result)) {
7543                         goto out;
7544                 }
7545                 DEBUG(4, ("we have:[%d] drivers in environment"
7546                           " [%s] and version [%d]\n",
7547                           num_drivers, architecture, version));
7548
7549                 if (num_drivers != 0) {
7550                         info = talloc_realloc(tmp_ctx, info,
7551                                                     union spoolss_DriverInfo,
7552                                                     count + num_drivers);
7553                         if (!info) {
7554                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7555                                         "failed to enlarge driver info buffer!\n"));
7556                                 result = WERR_NOMEM;
7557                                 goto out;
7558                         }
7559                 }
7560
7561                 for (i = 0; i < num_drivers; i++) {
7562                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7563
7564                         result = winreg_get_driver(tmp_ctx, b,
7565                                                    architecture, drivers[i],
7566                                                    version, &driver);
7567                         if (!W_ERROR_IS_OK(result)) {
7568                                 goto out;
7569                         }
7570
7571                         switch (level) {
7572                         case 1:
7573                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7574                                                                    driver, servername);
7575                                 break;
7576                         case 2:
7577                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7578                                                                    driver, servername);
7579                                 break;
7580                         case 3:
7581                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7582                                                                    driver, servername);
7583                                 break;
7584                         case 4:
7585                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7586                                                                    driver, servername);
7587                                 break;
7588                         case 5:
7589                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7590                                                                    driver, servername);
7591                                 break;
7592                         case 6:
7593                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7594                                                                    driver, servername);
7595                                 break;
7596                         case 8:
7597                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7598                                                                    driver, servername);
7599                                 break;
7600                         default:
7601                                 result = WERR_UNKNOWN_LEVEL;
7602                                 break;
7603                         }
7604
7605                         TALLOC_FREE(driver);
7606
7607                         if (!W_ERROR_IS_OK(result)) {
7608                                 goto out;
7609                         }
7610                 }
7611
7612                 count += num_drivers;
7613                 TALLOC_FREE(drivers);
7614         }
7615
7616 out:
7617         if (W_ERROR_IS_OK(result)) {
7618                 *info_p = talloc_move(mem_ctx, &info);
7619                 *count_p = count;
7620         }
7621
7622         talloc_free(tmp_ctx);
7623         return result;
7624 }
7625
7626 /****************************************************************************
7627  Enumerates all printer drivers by level.
7628 ****************************************************************************/
7629
7630 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7631                                        const struct auth_session_info *session_info,
7632                                        struct messaging_context *msg_ctx,
7633                                        const char *servername,
7634                                        const char *architecture,
7635                                        uint32_t level,
7636                                        union spoolss_DriverInfo **info_p,
7637                                        uint32_t *count_p)
7638 {
7639         uint32_t a,i;
7640         WERROR result = WERR_OK;
7641
7642         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7643
7644                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7645
7646                         union spoolss_DriverInfo *info = NULL;
7647                         uint32_t count = 0;
7648
7649                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7650                                                                           session_info,
7651                                                                           msg_ctx,
7652                                                                           servername,
7653                                                                           archi_table[a].long_archi,
7654                                                                           level,
7655                                                                           &info,
7656                                                                           &count);
7657                         if (!W_ERROR_IS_OK(result)) {
7658                                 continue;
7659                         }
7660
7661                         for (i=0; i < count; i++) {
7662                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7663                                              info[i], info_p, count_p);
7664                         }
7665                 }
7666
7667                 return result;
7668         }
7669
7670         return enumprinterdrivers_level_by_architecture(mem_ctx,
7671                                                         session_info,
7672                                                         msg_ctx,
7673                                                         servername,
7674                                                         architecture,
7675                                                         level,
7676                                                         info_p,
7677                                                         count_p);
7678 }
7679
7680 /****************************************************************
7681  _spoolss_EnumPrinterDrivers
7682 ****************************************************************/
7683
7684 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7685                                    struct spoolss_EnumPrinterDrivers *r)
7686 {
7687         const char *cservername;
7688         WERROR result;
7689
7690         /* that's an [in out] buffer */
7691
7692         if (!r->in.buffer && (r->in.offered != 0)) {
7693                 return WERR_INVALID_PARAM;
7694         }
7695
7696         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7697
7698         *r->out.needed = 0;
7699         *r->out.count = 0;
7700         *r->out.info = NULL;
7701
7702         cservername = canon_servername(r->in.server);
7703
7704         if (!is_myname_or_ipaddr(cservername)) {
7705                 return WERR_UNKNOWN_PRINTER_DRIVER;
7706         }
7707
7708         result = enumprinterdrivers_level(p->mem_ctx,
7709                                           get_session_info_system(),
7710                                           p->msg_ctx,
7711                                           cservername,
7712                                           r->in.environment,
7713                                           r->in.level,
7714                                           r->out.info,
7715                                           r->out.count);
7716         if (!W_ERROR_IS_OK(result)) {
7717                 return result;
7718         }
7719
7720         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7721                                                      spoolss_EnumPrinterDrivers,
7722                                                      *r->out.info, r->in.level,
7723                                                      *r->out.count);
7724         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7725         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7726
7727         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7728 }
7729
7730 /****************************************************************
7731  _spoolss_EnumForms
7732 ****************************************************************/
7733
7734 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7735                           struct spoolss_EnumForms *r)
7736 {
7737         WERROR result;
7738
7739         *r->out.count = 0;
7740         *r->out.needed = 0;
7741         *r->out.info = NULL;
7742
7743         /* that's an [in out] buffer */
7744
7745         if (!r->in.buffer && (r->in.offered != 0) ) {
7746                 return WERR_INVALID_PARAM;
7747         }
7748
7749         DEBUG(4,("_spoolss_EnumForms\n"));
7750         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7751         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7752
7753         switch (r->in.level) {
7754         case 1:
7755                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7756                                                    get_session_info_system(),
7757                                                    p->msg_ctx,
7758                                                    r->out.count,
7759                                                    r->out.info);
7760                 break;
7761         default:
7762                 result = WERR_UNKNOWN_LEVEL;
7763                 break;
7764         }
7765
7766         if (!W_ERROR_IS_OK(result)) {
7767                 return result;
7768         }
7769
7770         if (*r->out.count == 0) {
7771                 return WERR_NO_MORE_ITEMS;
7772         }
7773
7774         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7775                                                      spoolss_EnumForms,
7776                                                      *r->out.info, r->in.level,
7777                                                      *r->out.count);
7778         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7779         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7780
7781         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7782 }
7783
7784 /****************************************************************
7785  _spoolss_GetForm
7786 ****************************************************************/
7787
7788 WERROR _spoolss_GetForm(struct pipes_struct *p,
7789                         struct spoolss_GetForm *r)
7790 {
7791         WERROR result;
7792
7793         /* that's an [in out] buffer */
7794
7795         if (!r->in.buffer && (r->in.offered != 0)) {
7796                 return WERR_INVALID_PARAM;
7797         }
7798
7799         DEBUG(4,("_spoolss_GetForm\n"));
7800         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7801         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7802
7803         switch (r->in.level) {
7804         case 1:
7805                 result = winreg_printer_getform1_internal(p->mem_ctx,
7806                                                  get_session_info_system(),
7807                                                  p->msg_ctx,
7808                                                  r->in.form_name,
7809                                                  &r->out.info->info1);
7810                 break;
7811         default:
7812                 result = WERR_UNKNOWN_LEVEL;
7813                 break;
7814         }
7815
7816         if (!W_ERROR_IS_OK(result)) {
7817                 TALLOC_FREE(r->out.info);
7818                 return result;
7819         }
7820
7821         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7822                                                r->out.info, r->in.level);
7823         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7824
7825         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7826 }
7827
7828 /****************************************************************************
7829 ****************************************************************************/
7830
7831 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7832                           struct spoolss_PortInfo1 *r,
7833                           const char *name)
7834 {
7835         r->port_name = talloc_strdup(mem_ctx, name);
7836         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7837
7838         return WERR_OK;
7839 }
7840
7841 /****************************************************************************
7842  TODO: This probably needs distinguish between TCP/IP and Local ports
7843  somehow.
7844 ****************************************************************************/
7845
7846 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7847                           struct spoolss_PortInfo2 *r,
7848                           const char *name)
7849 {
7850         r->port_name = talloc_strdup(mem_ctx, name);
7851         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7852
7853         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7854         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7855
7856         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7857         W_ERROR_HAVE_NO_MEMORY(r->description);
7858
7859         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7860         r->reserved = 0;
7861
7862         return WERR_OK;
7863 }
7864
7865
7866 /****************************************************************************
7867  wrapper around the enumer ports command
7868 ****************************************************************************/
7869
7870 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7871 {
7872         char *cmd = lp_enumports_cmd(talloc_tos());
7873         char **qlines = NULL;
7874         char *command = NULL;
7875         int numlines;
7876         int ret;
7877         int fd;
7878
7879         *count = 0;
7880         *lines = NULL;
7881
7882         /* if no hook then just fill in the default port */
7883
7884         if ( !*cmd ) {
7885                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7886                         return WERR_NOMEM;
7887                 }
7888                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7889                         TALLOC_FREE(qlines);
7890                         return WERR_NOMEM;
7891                 }
7892                 qlines[1] = NULL;
7893                 numlines = 1;
7894         }
7895         else {
7896                 /* we have a valid enumport command */
7897
7898                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7899                 if (!command) {
7900                         return WERR_NOMEM;
7901                 }
7902
7903                 DEBUG(10,("Running [%s]\n", command));
7904                 ret = smbrun(command, &fd);
7905                 DEBUG(10,("Returned [%d]\n", ret));
7906                 TALLOC_FREE(command);
7907                 if (ret != 0) {
7908                         if (fd != -1) {
7909                                 close(fd);
7910                         }
7911                         return WERR_ACCESS_DENIED;
7912                 }
7913
7914                 numlines = 0;
7915                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7916                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7917                 close(fd);
7918         }
7919
7920         *count = numlines;
7921         *lines = qlines;
7922
7923         return WERR_OK;
7924 }
7925
7926 /****************************************************************************
7927  enumports level 1.
7928 ****************************************************************************/
7929
7930 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7931                                 union spoolss_PortInfo **info_p,
7932                                 uint32_t *count)
7933 {
7934         union spoolss_PortInfo *info = NULL;
7935         int i=0;
7936         WERROR result = WERR_OK;
7937         char **qlines = NULL;
7938         int numlines = 0;
7939
7940         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7941         if (!W_ERROR_IS_OK(result)) {
7942                 goto out;
7943         }
7944
7945         if (numlines) {
7946                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7947                 if (!info) {
7948                         DEBUG(10,("Returning WERR_NOMEM\n"));
7949                         result = WERR_NOMEM;
7950                         goto out;
7951                 }
7952
7953                 for (i=0; i<numlines; i++) {
7954                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7955                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7956                         if (!W_ERROR_IS_OK(result)) {
7957                                 goto out;
7958                         }
7959                 }
7960         }
7961         TALLOC_FREE(qlines);
7962
7963 out:
7964         if (!W_ERROR_IS_OK(result)) {
7965                 TALLOC_FREE(info);
7966                 TALLOC_FREE(qlines);
7967                 *count = 0;
7968                 *info_p = NULL;
7969                 return result;
7970         }
7971
7972         *info_p = info;
7973         *count = numlines;
7974
7975         return WERR_OK;
7976 }
7977
7978 /****************************************************************************
7979  enumports level 2.
7980 ****************************************************************************/
7981
7982 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7983                                 union spoolss_PortInfo **info_p,
7984                                 uint32_t *count)
7985 {
7986         union spoolss_PortInfo *info = NULL;
7987         int i=0;
7988         WERROR result = WERR_OK;
7989         char **qlines = NULL;
7990         int numlines = 0;
7991
7992         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7993         if (!W_ERROR_IS_OK(result)) {
7994                 goto out;
7995         }
7996
7997         if (numlines) {
7998                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7999                 if (!info) {
8000                         DEBUG(10,("Returning WERR_NOMEM\n"));
8001                         result = WERR_NOMEM;
8002                         goto out;
8003                 }
8004
8005                 for (i=0; i<numlines; i++) {
8006                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8007                         result = fill_port_2(info, &info[i].info2, qlines[i]);
8008                         if (!W_ERROR_IS_OK(result)) {
8009                                 goto out;
8010                         }
8011                 }
8012         }
8013         TALLOC_FREE(qlines);
8014
8015 out:
8016         if (!W_ERROR_IS_OK(result)) {
8017                 TALLOC_FREE(info);
8018                 TALLOC_FREE(qlines);
8019                 *count = 0;
8020                 *info_p = NULL;
8021                 return result;
8022         }
8023
8024         *info_p = info;
8025         *count = numlines;
8026
8027         return WERR_OK;
8028 }
8029
8030 /****************************************************************
8031  _spoolss_EnumPorts
8032 ****************************************************************/
8033
8034 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8035                           struct spoolss_EnumPorts *r)
8036 {
8037         WERROR result;
8038
8039         /* that's an [in out] buffer */
8040
8041         if (!r->in.buffer && (r->in.offered != 0)) {
8042                 return WERR_INVALID_PARAM;
8043         }
8044
8045         DEBUG(4,("_spoolss_EnumPorts\n"));
8046
8047         *r->out.count = 0;
8048         *r->out.needed = 0;
8049         *r->out.info = NULL;
8050
8051         switch (r->in.level) {
8052         case 1:
8053                 result = enumports_level_1(p->mem_ctx, r->out.info,
8054                                            r->out.count);
8055                 break;
8056         case 2:
8057                 result = enumports_level_2(p->mem_ctx, r->out.info,
8058                                            r->out.count);
8059                 break;
8060         default:
8061                 return WERR_UNKNOWN_LEVEL;
8062         }
8063
8064         if (!W_ERROR_IS_OK(result)) {
8065                 return result;
8066         }
8067
8068         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8069                                                      spoolss_EnumPorts,
8070                                                      *r->out.info, r->in.level,
8071                                                      *r->out.count);
8072         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8073         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8074
8075         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8076 }
8077
8078 /****************************************************************************
8079 ****************************************************************************/
8080
8081 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8082                                            const char *server,
8083                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8084                                            struct spoolss_DeviceMode *devmode,
8085                                            struct security_descriptor *secdesc,
8086                                            struct spoolss_UserLevelCtr *user_ctr,
8087                                            struct policy_handle *handle)
8088 {
8089         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8090         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8091         int     snum;
8092         WERROR err = WERR_OK;
8093
8094         /* samba does not have a concept of local, non-shared printers yet, so
8095          * make sure we always setup sharename - gd */
8096         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8097             (info2->printername != NULL && info2->printername[0] != '\0')) {
8098                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8099                         "no sharename has been set, setting printername %s as sharename\n",
8100                         info2->printername));
8101                 info2->sharename = info2->printername;
8102         }
8103
8104         /* check to see if the printer already exists */
8105         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8106                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8107                         info2->sharename));
8108                 return WERR_PRINTER_ALREADY_EXISTS;
8109         }
8110
8111         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8112                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8113                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8114                                 info2->printername));
8115                         return WERR_PRINTER_ALREADY_EXISTS;
8116                 }
8117         }
8118
8119         /* validate printer info struct */
8120         if (!info2->printername || strlen(info2->printername) == 0) {
8121                 return WERR_INVALID_PRINTER_NAME;
8122         }
8123         if (!info2->portname || strlen(info2->portname) == 0) {
8124                 return WERR_UNKNOWN_PORT;
8125         }
8126         if (!info2->drivername || strlen(info2->drivername) == 0) {
8127                 return WERR_UNKNOWN_PRINTER_DRIVER;
8128         }
8129         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8130                 return WERR_UNKNOWN_PRINTPROCESSOR;
8131         }
8132
8133         /* FIXME!!!  smbd should check to see if the driver is installed before
8134            trying to add a printer like this  --jerry */
8135
8136         if (*lp_addprinter_cmd(talloc_tos()) ) {
8137                 char *raddr;
8138
8139                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8140                                                          p->mem_ctx);
8141                 if (raddr == NULL) {
8142                         return WERR_NOMEM;
8143                 }
8144
8145                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8146                                        info2, raddr,
8147                                        p->msg_ctx) ) {
8148                         return WERR_ACCESS_DENIED;
8149                 }
8150         } else {
8151                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8152                         "smb.conf parameter \"addprinter command\" is defined. This "
8153                         "parameter must exist for this call to succeed\n",
8154                         info2->sharename ));
8155         }
8156
8157         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8158                 return WERR_ACCESS_DENIED;
8159         }
8160
8161         /* you must be a printer admin to add a new printer */
8162         if (!W_ERROR_IS_OK(print_access_check(p->session_info,
8163                                               p->msg_ctx,
8164                                               snum,
8165                                               PRINTER_ACCESS_ADMINISTER))) {
8166                 return WERR_ACCESS_DENIED;
8167         }
8168
8169         /*
8170          * Do sanity check on the requested changes for Samba.
8171          */
8172
8173         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8174                 return WERR_INVALID_PARAM;
8175         }
8176
8177         if (devmode == NULL) {
8178                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8179         }
8180
8181         err = update_dsspooler(p->mem_ctx,
8182                                get_session_info_system(),
8183                                p->msg_ctx,
8184                                0,
8185                                info2,
8186                                NULL);
8187         if (!W_ERROR_IS_OK(err)) {
8188                 return err;
8189         }
8190
8191         err = winreg_update_printer_internal(p->mem_ctx,
8192                                     get_session_info_system(),
8193                                     p->msg_ctx,
8194                                     info2->sharename,
8195                                     info2_mask,
8196                                     info2,
8197                                     devmode,
8198                                     secdesc);
8199         if (!W_ERROR_IS_OK(err)) {
8200                 return err;
8201         }
8202
8203         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8204         if (!W_ERROR_IS_OK(err)) {
8205                 /* Handle open failed - remove addition. */
8206                 ZERO_STRUCTP(handle);
8207                 return err;
8208         }
8209
8210         return WERR_OK;
8211 }
8212
8213 /****************************************************************
8214  _spoolss_AddPrinterEx
8215 ****************************************************************/
8216
8217 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8218                              struct spoolss_AddPrinterEx *r)
8219 {
8220         switch (r->in.info_ctr->level) {
8221         case 1:
8222                 /* we don't handle yet */
8223                 /* but I know what to do ... */
8224                 return WERR_UNKNOWN_LEVEL;
8225         case 2:
8226                 return spoolss_addprinterex_level_2(p, r->in.server,
8227                                                     r->in.info_ctr,
8228                                                     r->in.devmode_ctr->devmode,
8229                                                     r->in.secdesc_ctr->sd,
8230                                                     r->in.userlevel_ctr,
8231                                                     r->out.handle);
8232         default:
8233                 return WERR_UNKNOWN_LEVEL;
8234         }
8235 }
8236
8237 /****************************************************************
8238  _spoolss_AddPrinter
8239 ****************************************************************/
8240
8241 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8242                            struct spoolss_AddPrinter *r)
8243 {
8244         struct spoolss_AddPrinterEx a;
8245         struct spoolss_UserLevelCtr userlevel_ctr;
8246
8247         ZERO_STRUCT(userlevel_ctr);
8248
8249         userlevel_ctr.level = 1;
8250
8251         a.in.server             = r->in.server;
8252         a.in.info_ctr           = r->in.info_ctr;
8253         a.in.devmode_ctr        = r->in.devmode_ctr;
8254         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8255         a.in.userlevel_ctr      = &userlevel_ctr;
8256         a.out.handle            = r->out.handle;
8257
8258         return _spoolss_AddPrinterEx(p, &a);
8259 }
8260
8261 /****************************************************************
8262  _spoolss_AddPrinterDriverEx
8263 ****************************************************************/
8264
8265 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8266                                    struct spoolss_AddPrinterDriverEx *r)
8267 {
8268         WERROR err = WERR_OK;
8269         const char *driver_name = NULL;
8270         uint32_t version;
8271         const char *fn;
8272
8273         switch (p->opnum) {
8274                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8275                         fn = "_spoolss_AddPrinterDriver";
8276                         break;
8277                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8278                         fn = "_spoolss_AddPrinterDriverEx";
8279                         break;
8280                 default:
8281                         return WERR_INVALID_PARAM;
8282         }
8283
8284         /*
8285          * we only support the semantics of AddPrinterDriver()
8286          * i.e. only copy files that are newer than existing ones
8287          */
8288
8289         if (r->in.flags == 0) {
8290                 return WERR_INVALID_PARAM;
8291         }
8292
8293         if (r->in.flags != APD_COPY_NEW_FILES) {
8294                 return WERR_ACCESS_DENIED;
8295         }
8296
8297         /* FIXME */
8298         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8299                 /* Clever hack from Martin Zielinski <mz@seh.de>
8300                  * to allow downgrade from level 8 (Vista).
8301                  */
8302                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8303                         r->in.info_ctr->level));
8304                 return WERR_UNKNOWN_LEVEL;
8305         }
8306
8307         DEBUG(5,("Cleaning driver's information\n"));
8308         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8309         if (!W_ERROR_IS_OK(err))
8310                 goto done;
8311
8312         DEBUG(5,("Moving driver to final destination\n"));
8313         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8314         if (!W_ERROR_IS_OK(err)) {
8315                 goto done;
8316         }
8317
8318         err = winreg_add_driver_internal(p->mem_ctx,
8319                                 get_session_info_system(),
8320                                 p->msg_ctx,
8321                                 r->in.info_ctr,
8322                                 &driver_name,
8323                                 &version);
8324         if (!W_ERROR_IS_OK(err)) {
8325                 goto done;
8326         }
8327
8328         /*
8329          * I think this is where he DrvUpgradePrinter() hook would be
8330          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8331          * server.  Right now, we just need to send ourselves a message
8332          * to update each printer bound to this driver.   --jerry
8333          */
8334
8335         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8336                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8337                         fn, driver_name));
8338         }
8339
8340 done:
8341         return err;
8342 }
8343
8344 /****************************************************************
8345  _spoolss_AddPrinterDriver
8346 ****************************************************************/
8347
8348 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8349                                  struct spoolss_AddPrinterDriver *r)
8350 {
8351         struct spoolss_AddPrinterDriverEx a;
8352
8353         switch (r->in.info_ctr->level) {
8354         case 2:
8355         case 3:
8356         case 4:
8357         case 5:
8358                 break;
8359         default:
8360                 return WERR_UNKNOWN_LEVEL;
8361         }
8362
8363         a.in.servername         = r->in.servername;
8364         a.in.info_ctr           = r->in.info_ctr;
8365         a.in.flags              = APD_COPY_NEW_FILES;
8366
8367         return _spoolss_AddPrinterDriverEx(p, &a);
8368 }
8369
8370 /****************************************************************************
8371 ****************************************************************************/
8372
8373 struct _spoolss_paths {
8374         int type;
8375         const char *share;
8376         const char *dir;
8377 };
8378
8379 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8380
8381 static const struct _spoolss_paths spoolss_paths[]= {
8382         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8383         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8384 };
8385
8386 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8387                                           const char *servername,
8388                                           const char *environment,
8389                                           int component,
8390                                           char **path)
8391 {
8392         const char *pservername = NULL;
8393         const char *long_archi;
8394         const char *short_archi;
8395
8396         *path = NULL;
8397
8398         /* environment may be empty */
8399         if (environment && strlen(environment)) {
8400                 long_archi = environment;
8401         } else {
8402                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8403                                                   "spoolss", "architecture",
8404                                                   SPOOLSS_ARCHITECTURE_NT_X86);
8405         }
8406
8407         /* servername may be empty */
8408         if (servername && strlen(servername)) {
8409                 pservername = canon_servername(servername);
8410
8411                 if (!is_myname_or_ipaddr(pservername)) {
8412                         return WERR_INVALID_PARAM;
8413                 }
8414         }
8415
8416         if (!(short_archi = get_short_archi(long_archi))) {
8417                 return WERR_INVALID_ENVIRONMENT;
8418         }
8419
8420         switch (component) {
8421         case SPOOLSS_PRTPROCS_PATH:
8422         case SPOOLSS_DRIVER_PATH:
8423                 if (pservername) {
8424                         *path = talloc_asprintf(mem_ctx,
8425                                         "\\\\%s\\%s\\%s",
8426                                         pservername,
8427                                         spoolss_paths[component].share,
8428                                         short_archi);
8429                 } else {
8430                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8431                                         SPOOLSS_DEFAULT_SERVER_PATH,
8432                                         spoolss_paths[component].dir,
8433                                         short_archi);
8434                 }
8435                 break;
8436         default:
8437                 return WERR_INVALID_PARAM;
8438         }
8439
8440         if (!*path) {
8441                 return WERR_NOMEM;
8442         }
8443
8444         return WERR_OK;
8445 }
8446
8447 /****************************************************************************
8448 ****************************************************************************/
8449
8450 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8451                                           const char *servername,
8452                                           const char *environment,
8453                                           struct spoolss_DriverDirectoryInfo1 *r)
8454 {
8455         WERROR werr;
8456         char *path = NULL;
8457
8458         werr = compose_spoolss_server_path(mem_ctx,
8459                                            servername,
8460                                            environment,
8461                                            SPOOLSS_DRIVER_PATH,
8462                                            &path);
8463         if (!W_ERROR_IS_OK(werr)) {
8464                 return werr;
8465         }
8466
8467         DEBUG(4,("printer driver directory: [%s]\n", path));
8468
8469         r->directory_name = path;
8470
8471         return WERR_OK;
8472 }
8473
8474 /****************************************************************
8475  _spoolss_GetPrinterDriverDirectory
8476 ****************************************************************/
8477
8478 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8479                                           struct spoolss_GetPrinterDriverDirectory *r)
8480 {
8481         WERROR werror;
8482
8483         /* that's an [in out] buffer */
8484
8485         if (!r->in.buffer && (r->in.offered != 0)) {
8486                 return WERR_INVALID_PARAM;
8487         }
8488
8489         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8490                 r->in.level));
8491
8492         *r->out.needed = 0;
8493
8494         /* r->in.level is ignored */
8495
8496         werror = getprinterdriverdir_level_1(p->mem_ctx,
8497                                              r->in.server,
8498                                              r->in.environment,
8499                                              &r->out.info->info1);
8500         if (!W_ERROR_IS_OK(werror)) {
8501                 TALLOC_FREE(r->out.info);
8502                 return werror;
8503         }
8504
8505         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8506                                                r->out.info, r->in.level);
8507         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8508
8509         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8510 }
8511
8512 /****************************************************************
8513  _spoolss_EnumPrinterData
8514 ****************************************************************/
8515
8516 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8517                                 struct spoolss_EnumPrinterData *r)
8518 {
8519         WERROR result;
8520         struct spoolss_EnumPrinterDataEx r2;
8521         uint32_t count;
8522         struct spoolss_PrinterEnumValues *info, *val = NULL;
8523         uint32_t needed;
8524
8525         r2.in.handle    = r->in.handle;
8526         r2.in.key_name  = "PrinterDriverData";
8527         r2.in.offered   = 0;
8528         r2.out.count    = &count;
8529         r2.out.info     = &info;
8530         r2.out.needed   = &needed;
8531
8532         result = _spoolss_EnumPrinterDataEx(p, &r2);
8533         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8534                 r2.in.offered = needed;
8535                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8536         }
8537         if (!W_ERROR_IS_OK(result)) {
8538                 return result;
8539         }
8540
8541         /*
8542          * The NT machine wants to know the biggest size of value and data
8543          *
8544          * cf: MSDN EnumPrinterData remark section
8545          */
8546
8547         if (!r->in.value_offered && !r->in.data_offered) {
8548                 uint32_t biggest_valuesize = 0;
8549                 uint32_t biggest_datasize = 0;
8550                 int i, name_length;
8551
8552                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8553
8554                 for (i=0; i<count; i++) {
8555
8556                         name_length = strlen(info[i].value_name);
8557                         if (strlen(info[i].value_name) > biggest_valuesize) {
8558                                 biggest_valuesize = name_length;
8559                         }
8560
8561                         if (info[i].data_length > biggest_datasize) {
8562                                 biggest_datasize = info[i].data_length;
8563                         }
8564
8565                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8566                                 biggest_datasize));
8567                 }
8568
8569                 /* the value is an UNICODE string but real_value_size is the length
8570                    in bytes including the trailing 0 */
8571
8572                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8573                 *r->out.data_needed  = biggest_datasize;
8574
8575                 DEBUG(6,("final values: [%d], [%d]\n",
8576                         *r->out.value_needed, *r->out.data_needed));
8577
8578                 return WERR_OK;
8579         }
8580
8581         if (r->in.enum_index < count) {
8582                 val = &info[r->in.enum_index];
8583         }
8584
8585         if (val == NULL) {
8586                 /* out_value should default to "" or else NT4 has
8587                    problems unmarshalling the response */
8588
8589                 if (r->in.value_offered) {
8590                         *r->out.value_needed = 1;
8591                         r->out.value_name = talloc_strdup(r, "");
8592                         if (!r->out.value_name) {
8593                                 return WERR_NOMEM;
8594                         }
8595                 } else {
8596                         r->out.value_name = NULL;
8597                         *r->out.value_needed = 0;
8598                 }
8599
8600                 /* the data is counted in bytes */
8601
8602                 *r->out.data_needed = r->in.data_offered;
8603
8604                 result = WERR_NO_MORE_ITEMS;
8605         } else {
8606                 /*
8607                  * the value is:
8608                  * - counted in bytes in the request
8609                  * - counted in UNICODE chars in the max reply
8610                  * - counted in bytes in the real size
8611                  *
8612                  * take a pause *before* coding not *during* coding
8613                  */
8614
8615                 /* name */
8616                 if (r->in.value_offered) {
8617                         r->out.value_name = talloc_strdup(r, val->value_name);
8618                         if (!r->out.value_name) {
8619                                 return WERR_NOMEM;
8620                         }
8621                         *r->out.value_needed = val->value_name_len;
8622                 } else {
8623                         r->out.value_name = NULL;
8624                         *r->out.value_needed = 0;
8625                 }
8626
8627                 /* type */
8628
8629                 *r->out.type = val->type;
8630
8631                 /* data - counted in bytes */
8632
8633                 /*
8634                  * See the section "Dynamically Typed Query Parameters"
8635                  * in MS-RPRN.
8636                  */
8637
8638                 if (r->out.data && val->data && val->data->data &&
8639                                 val->data_length && r->in.data_offered) {
8640                         memcpy(r->out.data, val->data->data,
8641                                 MIN(val->data_length,r->in.data_offered));
8642                 }
8643
8644                 *r->out.data_needed = val->data_length;
8645
8646                 result = WERR_OK;
8647         }
8648
8649         return result;
8650 }
8651
8652 /****************************************************************
8653  _spoolss_SetPrinterData
8654 ****************************************************************/
8655
8656 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8657                                struct spoolss_SetPrinterData *r)
8658 {
8659         struct spoolss_SetPrinterDataEx r2;
8660
8661         r2.in.handle            = r->in.handle;
8662         r2.in.key_name          = "PrinterDriverData";
8663         r2.in.value_name        = r->in.value_name;
8664         r2.in.type              = r->in.type;
8665         r2.in.data              = r->in.data;
8666         r2.in.offered           = r->in.offered;
8667
8668         return _spoolss_SetPrinterDataEx(p, &r2);
8669 }
8670
8671 /****************************************************************
8672  _spoolss_ResetPrinter
8673 ****************************************************************/
8674
8675 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8676                              struct spoolss_ResetPrinter *r)
8677 {
8678         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8679         int             snum;
8680
8681         DEBUG(5,("_spoolss_ResetPrinter\n"));
8682
8683         /*
8684          * All we do is to check to see if the handle and queue is valid.
8685          * This call really doesn't mean anything to us because we only
8686          * support RAW printing.   --jerry
8687          */
8688
8689         if (!Printer) {
8690                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8691                         OUR_HANDLE(r->in.handle)));
8692                 return WERR_BADFID;
8693         }
8694
8695         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8696                 return WERR_BADFID;
8697
8698
8699         /* blindly return success */
8700         return WERR_OK;
8701 }
8702
8703 /****************************************************************
8704  _spoolss_DeletePrinterData
8705 ****************************************************************/
8706
8707 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8708                                   struct spoolss_DeletePrinterData *r)
8709 {
8710         struct spoolss_DeletePrinterDataEx r2;
8711
8712         r2.in.handle            = r->in.handle;
8713         r2.in.key_name          = "PrinterDriverData";
8714         r2.in.value_name        = r->in.value_name;
8715
8716         return _spoolss_DeletePrinterDataEx(p, &r2);
8717 }
8718
8719 /****************************************************************
8720  _spoolss_AddForm
8721 ****************************************************************/
8722
8723 WERROR _spoolss_AddForm(struct pipes_struct *p,
8724                         struct spoolss_AddForm *r)
8725 {
8726         struct spoolss_AddFormInfo1 *form;
8727         int snum = -1;
8728         WERROR status = WERR_OK;
8729         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8730         struct dcerpc_binding_handle *b;
8731         TALLOC_CTX *tmp_ctx = NULL;
8732
8733         DEBUG(5,("_spoolss_AddForm\n"));
8734
8735         if (!Printer) {
8736                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8737                         OUR_HANDLE(r->in.handle)));
8738                 return WERR_BADFID;
8739         }
8740
8741         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8742            and not a printer admin, then fail */
8743
8744         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8745             !security_token_has_privilege(p->session_info->security_token,
8746                                           SEC_PRIV_PRINT_OPERATOR)) {
8747                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8748                 return WERR_ACCESS_DENIED;
8749         }
8750
8751         if (r->in.info_ctr->level != 1) {
8752                 return WERR_INVALID_LEVEL;
8753         }
8754
8755         form = r->in.info_ctr->info.info1;
8756         if (!form) {
8757                 return WERR_INVALID_PARAM;
8758         }
8759
8760         switch (form->flags) {
8761         case SPOOLSS_FORM_USER:
8762         case SPOOLSS_FORM_BUILTIN:
8763         case SPOOLSS_FORM_PRINTER:
8764                 break;
8765         default:
8766                 return WERR_INVALID_PARAM;
8767         }
8768
8769         tmp_ctx = talloc_new(p->mem_ctx);
8770         if (!tmp_ctx) {
8771                 return WERR_NOMEM;
8772         }
8773
8774         status = winreg_printer_binding_handle(tmp_ctx,
8775                                                get_session_info_system(),
8776                                                p->msg_ctx,
8777                                                &b);
8778         if (!W_ERROR_IS_OK(status)) {
8779                 goto done;
8780         }
8781
8782         status = winreg_printer_addform1(tmp_ctx, b, form);
8783         if (!W_ERROR_IS_OK(status)) {
8784                 goto done;
8785         }
8786
8787         /*
8788          * ChangeID must always be set if this is a printer
8789          */
8790         if (Printer->printer_type == SPLHND_PRINTER) {
8791                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8792                         status = WERR_BADFID;
8793                         goto done;
8794                 }
8795
8796                 status = winreg_printer_update_changeid(tmp_ctx, b,
8797                                                         lp_const_servicename(snum));
8798         }
8799
8800 done:
8801         talloc_free(tmp_ctx);
8802         return status;
8803 }
8804
8805 /****************************************************************
8806  _spoolss_DeleteForm
8807 ****************************************************************/
8808
8809 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8810                            struct spoolss_DeleteForm *r)
8811 {
8812         const char *form_name = r->in.form_name;
8813         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8814         int snum = -1;
8815         WERROR status = WERR_OK;
8816         struct dcerpc_binding_handle *b;
8817         TALLOC_CTX *tmp_ctx = NULL;
8818
8819         DEBUG(5,("_spoolss_DeleteForm\n"));
8820
8821         if (!Printer) {
8822                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8823                         OUR_HANDLE(r->in.handle)));
8824                 return WERR_BADFID;
8825         }
8826
8827         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8828             !security_token_has_privilege(p->session_info->security_token,
8829                                           SEC_PRIV_PRINT_OPERATOR)) {
8830                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8831                 return WERR_ACCESS_DENIED;
8832         }
8833
8834         tmp_ctx = talloc_new(p->mem_ctx);
8835         if (!tmp_ctx) {
8836                 return WERR_NOMEM;
8837         }
8838
8839         status = winreg_printer_binding_handle(tmp_ctx,
8840                                                get_session_info_system(),
8841                                                p->msg_ctx,
8842                                                &b);
8843         if (!W_ERROR_IS_OK(status)) {
8844                 goto done;
8845         }
8846
8847         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8848         if (!W_ERROR_IS_OK(status)) {
8849                 goto done;
8850         }
8851
8852         /*
8853          * ChangeID must always be set if this is a printer
8854          */
8855         if (Printer->printer_type == SPLHND_PRINTER) {
8856                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8857                         status = WERR_BADFID;
8858                         goto done;
8859                 }
8860
8861                 status = winreg_printer_update_changeid(tmp_ctx, b,
8862                                                         lp_const_servicename(snum));
8863         }
8864
8865 done:
8866         talloc_free(tmp_ctx);
8867         return status;
8868 }
8869
8870 /****************************************************************
8871  _spoolss_SetForm
8872 ****************************************************************/
8873
8874 WERROR _spoolss_SetForm(struct pipes_struct *p,
8875                         struct spoolss_SetForm *r)
8876 {
8877         struct spoolss_AddFormInfo1 *form;
8878         const char *form_name = r->in.form_name;
8879         int snum = -1;
8880         WERROR status = WERR_OK;
8881         struct dcerpc_binding_handle *b;
8882         TALLOC_CTX *tmp_ctx = NULL;
8883
8884         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8885
8886         DEBUG(5,("_spoolss_SetForm\n"));
8887
8888         if (!Printer) {
8889                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8890                         OUR_HANDLE(r->in.handle)));
8891                 return WERR_BADFID;
8892         }
8893
8894         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8895            and not a printer admin, then fail */
8896
8897         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8898              !security_token_has_privilege(p->session_info->security_token,
8899                                            SEC_PRIV_PRINT_OPERATOR)) {
8900                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8901                 return WERR_ACCESS_DENIED;
8902         }
8903
8904         if (r->in.info_ctr->level != 1) {
8905                 return WERR_INVALID_LEVEL;
8906         }
8907
8908         form = r->in.info_ctr->info.info1;
8909         if (!form) {
8910                 return WERR_INVALID_PARAM;
8911         }
8912
8913         tmp_ctx = talloc_new(p->mem_ctx);
8914         if (!tmp_ctx) {
8915                 return WERR_NOMEM;
8916         }
8917
8918         status = winreg_printer_binding_handle(tmp_ctx,
8919                                                get_session_info_system(),
8920                                                p->msg_ctx,
8921                                                &b);
8922         if (!W_ERROR_IS_OK(status)) {
8923                 goto done;
8924         }
8925
8926         status = winreg_printer_setform1(tmp_ctx, b,
8927                                          form_name,
8928                                          form);
8929         if (!W_ERROR_IS_OK(status)) {
8930                 goto done;
8931         }
8932
8933         /*
8934          * ChangeID must always be set if this is a printer
8935          */
8936         if (Printer->printer_type == SPLHND_PRINTER) {
8937                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8938                         status = WERR_BADFID;
8939                         goto done;
8940                 }
8941
8942                 status = winreg_printer_update_changeid(tmp_ctx, b,
8943                                                         lp_const_servicename(snum));
8944         }
8945
8946 done:
8947         talloc_free(tmp_ctx);
8948         return status;
8949 }
8950
8951 /****************************************************************************
8952  fill_print_processor1
8953 ****************************************************************************/
8954
8955 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8956                                     struct spoolss_PrintProcessorInfo1 *r,
8957                                     const char *print_processor_name)
8958 {
8959         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8960         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8961
8962         return WERR_OK;
8963 }
8964
8965 /****************************************************************************
8966  enumprintprocessors level 1.
8967 ****************************************************************************/
8968
8969 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8970                                           union spoolss_PrintProcessorInfo **info_p,
8971                                           uint32_t *count)
8972 {
8973         union spoolss_PrintProcessorInfo *info;
8974         WERROR result;
8975
8976         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8977         W_ERROR_HAVE_NO_MEMORY(info);
8978
8979         *count = 1;
8980
8981         result = fill_print_processor1(info, &info[0].info1, "winprint");
8982         if (!W_ERROR_IS_OK(result)) {
8983                 goto out;
8984         }
8985
8986  out:
8987         if (!W_ERROR_IS_OK(result)) {
8988                 TALLOC_FREE(info);
8989                 *count = 0;
8990                 return result;
8991         }
8992
8993         *info_p = info;
8994
8995         return WERR_OK;
8996 }
8997
8998 /****************************************************************
8999  _spoolss_EnumPrintProcessors
9000 ****************************************************************/
9001
9002 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9003                                     struct spoolss_EnumPrintProcessors *r)
9004 {
9005         WERROR result;
9006
9007         /* that's an [in out] buffer */
9008
9009         if (!r->in.buffer && (r->in.offered != 0)) {
9010                 return WERR_INVALID_PARAM;
9011         }
9012
9013         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9014
9015         /*
9016          * Enumerate the print processors ...
9017          *
9018          * Just reply with "winprint", to keep NT happy
9019          * and I can use my nice printer checker.
9020          */
9021
9022         *r->out.count = 0;
9023         *r->out.needed = 0;
9024         *r->out.info = NULL;
9025
9026         if (!get_short_archi(r->in.environment)) {
9027                 return WERR_INVALID_ENVIRONMENT;
9028         }
9029
9030         switch (r->in.level) {
9031         case 1:
9032                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9033                                                      r->out.count);
9034                 break;
9035         default:
9036                 return WERR_UNKNOWN_LEVEL;
9037         }
9038
9039         if (!W_ERROR_IS_OK(result)) {
9040                 return result;
9041         }
9042
9043         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9044                                                      spoolss_EnumPrintProcessors,
9045                                                      *r->out.info, r->in.level,
9046                                                      *r->out.count);
9047         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9048         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9049
9050         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9051 }
9052
9053 /****************************************************************************
9054  fill_printprocdatatype1
9055 ****************************************************************************/
9056
9057 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9058                                       struct spoolss_PrintProcDataTypesInfo1 *r,
9059                                       const char *name_array)
9060 {
9061         r->name_array = talloc_strdup(mem_ctx, name_array);
9062         W_ERROR_HAVE_NO_MEMORY(r->name_array);
9063
9064         return WERR_OK;
9065 }
9066
9067 /****************************************************************************
9068  enumprintprocdatatypes level 1.
9069 ****************************************************************************/
9070
9071 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9072                                              union spoolss_PrintProcDataTypesInfo **info_p,
9073                                              uint32_t *count)
9074 {
9075         WERROR result;
9076         union spoolss_PrintProcDataTypesInfo *info;
9077
9078         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9079         W_ERROR_HAVE_NO_MEMORY(info);
9080
9081         *count = 1;
9082
9083         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9084         if (!W_ERROR_IS_OK(result)) {
9085                 goto out;
9086         }
9087
9088  out:
9089         if (!W_ERROR_IS_OK(result)) {
9090                 TALLOC_FREE(info);
9091                 *count = 0;
9092                 return result;
9093         }
9094
9095         *info_p = info;
9096
9097         return WERR_OK;
9098 }
9099
9100 /****************************************************************
9101  _spoolss_EnumPrintProcDataTypes
9102 ****************************************************************/
9103
9104 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9105                                        struct spoolss_EnumPrintProcDataTypes *r)
9106 {
9107         WERROR result;
9108
9109         /* that's an [in out] buffer */
9110
9111         if (!r->in.buffer && (r->in.offered != 0)) {
9112                 return WERR_INVALID_PARAM;
9113         }
9114
9115         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9116
9117         *r->out.count = 0;
9118         *r->out.needed = 0;
9119         *r->out.info = NULL;
9120
9121         if (r->in.print_processor_name == NULL ||
9122             !strequal(r->in.print_processor_name, "winprint")) {
9123                 return WERR_UNKNOWN_PRINTPROCESSOR;
9124         }
9125
9126         switch (r->in.level) {
9127         case 1:
9128                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9129                                                         r->out.count);
9130                 break;
9131         default:
9132                 return WERR_UNKNOWN_LEVEL;
9133         }
9134
9135         if (!W_ERROR_IS_OK(result)) {
9136                 return result;
9137         }
9138
9139         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9140                                                      spoolss_EnumPrintProcDataTypes,
9141                                                      *r->out.info, r->in.level,
9142                                                      *r->out.count);
9143         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9144         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9145
9146         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9147 }
9148
9149 /****************************************************************************
9150  fill_monitor_1
9151 ****************************************************************************/
9152
9153 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9154                              struct spoolss_MonitorInfo1 *r,
9155                              const char *monitor_name)
9156 {
9157         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9158         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9159
9160         return WERR_OK;
9161 }
9162
9163 /****************************************************************************
9164  fill_monitor_2
9165 ****************************************************************************/
9166
9167 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9168                              struct spoolss_MonitorInfo2 *r,
9169                              const char *monitor_name,
9170                              const char *environment,
9171                              const char *dll_name)
9172 {
9173         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9174         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9175         r->environment                  = talloc_strdup(mem_ctx, environment);
9176         W_ERROR_HAVE_NO_MEMORY(r->environment);
9177         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9178         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9179
9180         return WERR_OK;
9181 }
9182
9183 /****************************************************************************
9184  enumprintmonitors level 1.
9185 ****************************************************************************/
9186
9187 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9188                                         union spoolss_MonitorInfo **info_p,
9189                                         uint32_t *count)
9190 {
9191         union spoolss_MonitorInfo *info;
9192         WERROR result = WERR_OK;
9193
9194         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9195         W_ERROR_HAVE_NO_MEMORY(info);
9196
9197         *count = 2;
9198
9199         result = fill_monitor_1(info, &info[0].info1,
9200                                 SPL_LOCAL_PORT);
9201         if (!W_ERROR_IS_OK(result)) {
9202                 goto out;
9203         }
9204
9205         result = fill_monitor_1(info, &info[1].info1,
9206                                 SPL_TCPIP_PORT);
9207         if (!W_ERROR_IS_OK(result)) {
9208                 goto out;
9209         }
9210
9211 out:
9212         if (!W_ERROR_IS_OK(result)) {
9213                 TALLOC_FREE(info);
9214                 *count = 0;
9215                 return result;
9216         }
9217
9218         *info_p = info;
9219
9220         return WERR_OK;
9221 }
9222
9223 /****************************************************************************
9224  enumprintmonitors level 2.
9225 ****************************************************************************/
9226
9227 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9228                                         union spoolss_MonitorInfo **info_p,
9229                                         uint32_t *count)
9230 {
9231         union spoolss_MonitorInfo *info;
9232         WERROR result = WERR_OK;
9233
9234         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9235         W_ERROR_HAVE_NO_MEMORY(info);
9236
9237         *count = 2;
9238
9239         result = fill_monitor_2(info, &info[0].info2,
9240                                 SPL_LOCAL_PORT,
9241                                 "Windows NT X86", /* FIXME */
9242                                 "localmon.dll");
9243         if (!W_ERROR_IS_OK(result)) {
9244                 goto out;
9245         }
9246
9247         result = fill_monitor_2(info, &info[1].info2,
9248                                 SPL_TCPIP_PORT,
9249                                 "Windows NT X86", /* FIXME */
9250                                 "tcpmon.dll");
9251         if (!W_ERROR_IS_OK(result)) {
9252                 goto out;
9253         }
9254
9255 out:
9256         if (!W_ERROR_IS_OK(result)) {
9257                 TALLOC_FREE(info);
9258                 *count = 0;
9259                 return result;
9260         }
9261
9262         *info_p = info;
9263
9264         return WERR_OK;
9265 }
9266
9267 /****************************************************************
9268  _spoolss_EnumMonitors
9269 ****************************************************************/
9270
9271 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9272                              struct spoolss_EnumMonitors *r)
9273 {
9274         WERROR result;
9275
9276         /* that's an [in out] buffer */
9277
9278         if (!r->in.buffer && (r->in.offered != 0)) {
9279                 return WERR_INVALID_PARAM;
9280         }
9281
9282         DEBUG(5,("_spoolss_EnumMonitors\n"));
9283
9284         /*
9285          * Enumerate the print monitors ...
9286          *
9287          * Just reply with "Local Port", to keep NT happy
9288          * and I can use my nice printer checker.
9289          */
9290
9291         *r->out.count = 0;
9292         *r->out.needed = 0;
9293         *r->out.info = NULL;
9294
9295         switch (r->in.level) {
9296         case 1:
9297                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9298                                                    r->out.count);
9299                 break;
9300         case 2:
9301                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9302                                                    r->out.count);
9303                 break;
9304         default:
9305                 return WERR_UNKNOWN_LEVEL;
9306         }
9307
9308         if (!W_ERROR_IS_OK(result)) {
9309                 return result;
9310         }
9311
9312         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9313                                                      spoolss_EnumMonitors,
9314                                                      *r->out.info, r->in.level,
9315                                                      *r->out.count);
9316         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9317         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9318
9319         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9320 }
9321
9322 /****************************************************************************
9323 ****************************************************************************/
9324
9325 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9326                              const print_queue_struct *queue,
9327                              int count, int snum,
9328                              struct spoolss_PrinterInfo2 *pinfo2,
9329                              uint32_t jobid,
9330                              struct spoolss_JobInfo1 *r)
9331 {
9332         int i = 0;
9333         bool found = false;
9334
9335         for (i=0; i<count; i++) {
9336                 if (queue[i].sysjob == (int)jobid) {
9337                         found = true;
9338                         break;
9339                 }
9340         }
9341
9342         if (found == false) {
9343                 /* NT treats not found as bad param... yet another bad choice */
9344                 return WERR_INVALID_PARAM;
9345         }
9346
9347         return fill_job_info1(mem_ctx,
9348                               r,
9349                               &queue[i],
9350                               i,
9351                               snum,
9352                               pinfo2);
9353 }
9354
9355 /****************************************************************************
9356 ****************************************************************************/
9357
9358 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9359                              const print_queue_struct *queue,
9360                              int count, int snum,
9361                              struct spoolss_PrinterInfo2 *pinfo2,
9362                              uint32_t jobid,
9363                              struct spoolss_JobInfo2 *r)
9364 {
9365         int i = 0;
9366         bool found = false;
9367         struct spoolss_DeviceMode *devmode;
9368         WERROR result;
9369
9370         for (i=0; i<count; i++) {
9371                 if (queue[i].sysjob == (int)jobid) {
9372                         found = true;
9373                         break;
9374                 }
9375         }
9376
9377         if (found == false) {
9378                 /* NT treats not found as bad param... yet another bad
9379                    choice */
9380                 return WERR_INVALID_PARAM;
9381         }
9382
9383         /*
9384          * if the print job does not have a DEVMODE associated with it,
9385          * just use the one for the printer. A NULL devicemode is not
9386          *  a failure condition
9387          */
9388
9389         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9390         if (!devmode) {
9391                 result = spoolss_create_default_devmode(mem_ctx,
9392                                                 pinfo2->printername,
9393                                                 &devmode);
9394                 if (!W_ERROR_IS_OK(result)) {
9395                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9396                         return result;
9397                 }
9398         }
9399
9400         return fill_job_info2(mem_ctx,
9401                               r,
9402                               &queue[i],
9403                               i,
9404                               snum,
9405                               pinfo2,
9406                               devmode);
9407 }
9408
9409 /****************************************************************
9410  _spoolss_GetJob
9411 ****************************************************************/
9412
9413 WERROR _spoolss_GetJob(struct pipes_struct *p,
9414                        struct spoolss_GetJob *r)
9415 {
9416         WERROR result = WERR_OK;
9417         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9418         int snum;
9419         int count;
9420         print_queue_struct      *queue = NULL;
9421         print_status_struct prt_status;
9422
9423         /* that's an [in out] buffer */
9424
9425         if (!r->in.buffer && (r->in.offered != 0)) {
9426                 return WERR_INVALID_PARAM;
9427         }
9428
9429         DEBUG(5,("_spoolss_GetJob\n"));
9430
9431         *r->out.needed = 0;
9432
9433         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9434                 return WERR_BADFID;
9435         }
9436
9437         result = winreg_get_printer_internal(p->mem_ctx,
9438                                     get_session_info_system(),
9439                                     p->msg_ctx,
9440                                     lp_const_servicename(snum),
9441                                     &pinfo2);
9442         if (!W_ERROR_IS_OK(result)) {
9443                 return result;
9444         }
9445
9446         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9447
9448         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9449                      count, prt_status.status, prt_status.message));
9450
9451         switch (r->in.level) {
9452         case 1:
9453                 result = getjob_level_1(p->mem_ctx,
9454                                         queue, count, snum, pinfo2,
9455                                         r->in.job_id, &r->out.info->info1);
9456                 break;
9457         case 2:
9458                 result = getjob_level_2(p->mem_ctx,
9459                                         queue, count, snum, pinfo2,
9460                                         r->in.job_id, &r->out.info->info2);
9461                 break;
9462         default:
9463                 result = WERR_UNKNOWN_LEVEL;
9464                 break;
9465         }
9466
9467         SAFE_FREE(queue);
9468         TALLOC_FREE(pinfo2);
9469
9470         if (!W_ERROR_IS_OK(result)) {
9471                 TALLOC_FREE(r->out.info);
9472                 return result;
9473         }
9474
9475         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9476                                                                                    r->in.level);
9477         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9478
9479         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9480 }
9481
9482 /****************************************************************
9483  _spoolss_GetPrinterDataEx
9484 ****************************************************************/
9485
9486 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9487                                  struct spoolss_GetPrinterDataEx *r)
9488 {
9489
9490         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9491         const char *printer;
9492         int                     snum = 0;
9493         WERROR result = WERR_OK;
9494         DATA_BLOB blob;
9495         enum winreg_Type val_type = REG_NONE;
9496         uint8_t *val_data = NULL;
9497         uint32_t val_size = 0;
9498         struct dcerpc_binding_handle *b;
9499         TALLOC_CTX *tmp_ctx;
9500
9501         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9502
9503         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9504                 r->in.key_name, r->in.value_name));
9505
9506         /* in case of problem, return some default values */
9507
9508         *r->out.needed  = 0;
9509         *r->out.type    = REG_NONE;
9510
9511         tmp_ctx = talloc_new(p->mem_ctx);
9512         if (!tmp_ctx) {
9513                 return WERR_NOMEM;
9514         }
9515
9516         if (!Printer) {
9517                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9518                         OUR_HANDLE(r->in.handle)));
9519                 result = WERR_BADFID;
9520                 goto done;
9521         }
9522
9523         /* check to see if the keyname is valid */
9524         if (!strlen(r->in.key_name)) {
9525                 result = WERR_INVALID_PARAM;
9526                 goto done;
9527         }
9528
9529         /* Is the handle to a printer or to the server? */
9530
9531         if (Printer->printer_type == SPLHND_SERVER) {
9532
9533                 union spoolss_PrinterData data;
9534
9535                 result = getprinterdata_printer_server(tmp_ctx,
9536                                                        r->in.value_name,
9537                                                        r->out.type,
9538                                                        &data);
9539                 if (!W_ERROR_IS_OK(result)) {
9540                         goto done;
9541                 }
9542
9543                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9544                                                   *r->out.type, &data);
9545                 if (!W_ERROR_IS_OK(result)) {
9546                         goto done;
9547                 }
9548
9549                 *r->out.needed = blob.length;
9550
9551                 if (r->in.offered >= *r->out.needed) {
9552                         memcpy(r->out.data, blob.data, blob.length);
9553                 }
9554
9555                 result = WERR_OK;
9556                 goto done;
9557         }
9558
9559         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9560                 result = WERR_BADFID;
9561                 goto done;
9562         }
9563         printer = lp_const_servicename(snum);
9564
9565         result = winreg_printer_binding_handle(tmp_ctx,
9566                                                get_session_info_system(),
9567                                                p->msg_ctx,
9568                                                &b);
9569         if (!W_ERROR_IS_OK(result)) {
9570                 goto done;
9571         }
9572
9573         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9574         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9575             strequal(r->in.value_name, "ChangeId")) {
9576                 *r->out.type = REG_DWORD;
9577                 *r->out.needed = 4;
9578                 if (r->in.offered >= *r->out.needed) {
9579                         uint32_t changeid = 0;
9580
9581                         result = winreg_printer_get_changeid(tmp_ctx, b,
9582                                                              printer,
9583                                                              &changeid);
9584                         if (!W_ERROR_IS_OK(result)) {
9585                                 goto done;
9586                         }
9587
9588                         SIVAL(r->out.data, 0, changeid);
9589                         result = WERR_OK;
9590                 }
9591                 goto done;
9592         }
9593
9594         result = winreg_get_printer_dataex(tmp_ctx, b,
9595                                            printer,
9596                                            r->in.key_name,
9597                                            r->in.value_name,
9598                                            &val_type,
9599                                            &val_data,
9600                                            &val_size);
9601         if (!W_ERROR_IS_OK(result)) {
9602                 goto done;
9603         }
9604
9605         *r->out.needed = val_size;
9606         *r->out.type = val_type;
9607
9608         if (r->in.offered >= *r->out.needed) {
9609                 memcpy(r->out.data, val_data, val_size);
9610         }
9611
9612 done:
9613         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9614
9615         if (W_ERROR_IS_OK(result)) {
9616                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9617         }
9618
9619         talloc_free(tmp_ctx);
9620         return result;
9621 }
9622
9623 /****************************************************************
9624  _spoolss_SetPrinterDataEx
9625 ****************************************************************/
9626
9627 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9628                                  struct spoolss_SetPrinterDataEx *r)
9629 {
9630         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9631         int                     snum = 0;
9632         WERROR                  result = WERR_OK;
9633         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9634         char                    *oid_string;
9635         struct dcerpc_binding_handle *b;
9636         TALLOC_CTX *tmp_ctx;
9637
9638         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9639
9640         /* From MSDN documentation of SetPrinterDataEx: pass request to
9641            SetPrinterData if key is "PrinterDriverData" */
9642
9643         if (!Printer) {
9644                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9645                         OUR_HANDLE(r->in.handle)));
9646                 return WERR_BADFID;
9647         }
9648
9649         if (Printer->printer_type == SPLHND_SERVER) {
9650                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9651                         "Not implemented for server handles yet\n"));
9652                 return WERR_INVALID_PARAM;
9653         }
9654
9655         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9656                 return WERR_BADFID;
9657         }
9658
9659         /*
9660          * Access check : NT returns "access denied" if you make a
9661          * SetPrinterData call without the necessary privildge.
9662          * we were originally returning OK if nothing changed
9663          * which made Win2k issue **a lot** of SetPrinterData
9664          * when connecting to a printer  --jerry
9665          */
9666
9667         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9668                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9669                         "change denied by handle access permissions\n"));
9670                 return WERR_ACCESS_DENIED;
9671         }
9672
9673         tmp_ctx = talloc_new(p->mem_ctx);
9674         if (!tmp_ctx) {
9675                 return WERR_NOMEM;
9676         }
9677
9678         result = winreg_printer_binding_handle(tmp_ctx,
9679                                                get_session_info_system(),
9680                                                p->msg_ctx,
9681                                                &b);
9682         if (!W_ERROR_IS_OK(result)) {
9683                 goto done;
9684         }
9685
9686         result = winreg_get_printer(tmp_ctx, b,
9687                                     lp_servicename(talloc_tos(), snum),
9688                                     &pinfo2);
9689         if (!W_ERROR_IS_OK(result)) {
9690                 goto done;
9691         }
9692
9693         /* check for OID in valuename */
9694
9695         oid_string = strchr(r->in.value_name, ',');
9696         if (oid_string) {
9697                 *oid_string = '\0';
9698                 oid_string++;
9699         }
9700
9701         /* save the registry data */
9702
9703         result = winreg_set_printer_dataex(tmp_ctx, b,
9704                                            pinfo2->sharename,
9705                                            r->in.key_name,
9706                                            r->in.value_name,
9707                                            r->in.type,
9708                                            r->in.data,
9709                                            r->in.offered);
9710
9711         if (W_ERROR_IS_OK(result)) {
9712                 /* save the OID if one was specified */
9713                 if (oid_string) {
9714                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9715                                 r->in.key_name, SPOOL_OID_KEY);
9716                         if (!str) {
9717                                 result = WERR_NOMEM;
9718                                 goto done;
9719                         }
9720
9721                         /*
9722                          * I'm not checking the status here on purpose.  Don't know
9723                          * if this is right, but I'm returning the status from the
9724                          * previous set_printer_dataex() call.  I have no idea if
9725                          * this is right.    --jerry
9726                          */
9727                         winreg_set_printer_dataex(tmp_ctx, b,
9728                                                   pinfo2->sharename,
9729                                                   str,
9730                                                   r->in.value_name,
9731                                                   REG_SZ,
9732                                                   (uint8_t *) oid_string,
9733                                                   strlen(oid_string) + 1);
9734                 }
9735
9736                 result = winreg_printer_update_changeid(tmp_ctx, b,
9737                                                         lp_const_servicename(snum));
9738
9739         }
9740
9741 done:
9742         talloc_free(tmp_ctx);
9743         return result;
9744 }
9745
9746 /****************************************************************
9747  _spoolss_DeletePrinterDataEx
9748 ****************************************************************/
9749
9750 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9751                                     struct spoolss_DeletePrinterDataEx *r)
9752 {
9753         const char *printer;
9754         int             snum=0;
9755         WERROR          status = WERR_OK;
9756         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9757
9758         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9759
9760         if (!Printer) {
9761                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9762                         "Invalid handle (%s:%u:%u).\n",
9763                         OUR_HANDLE(r->in.handle)));
9764                 return WERR_BADFID;
9765         }
9766
9767         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9768                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9769                         "printer properties change denied by handle\n"));
9770                 return WERR_ACCESS_DENIED;
9771         }
9772
9773         if (!r->in.value_name || !r->in.key_name) {
9774                 return WERR_NOMEM;
9775         }
9776
9777         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9778                 return WERR_BADFID;
9779         }
9780         printer = lp_const_servicename(snum);
9781
9782         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9783                                               get_session_info_system(),
9784                                               p->msg_ctx,
9785                                               printer,
9786                                               r->in.key_name,
9787                                               r->in.value_name);
9788         if (W_ERROR_IS_OK(status)) {
9789                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9790                                                         get_session_info_system(),
9791                                                         p->msg_ctx,
9792                                                         printer);
9793         }
9794
9795         return status;
9796 }
9797
9798 /****************************************************************
9799  _spoolss_EnumPrinterKey
9800 ****************************************************************/
9801
9802 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9803                                struct spoolss_EnumPrinterKey *r)
9804 {
9805         uint32_t        num_keys;
9806         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9807         int             snum = 0;
9808         WERROR          result = WERR_BADFILE;
9809         const char **array = NULL;
9810         DATA_BLOB blob;
9811
9812         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9813
9814         if (!Printer) {
9815                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9816                         OUR_HANDLE(r->in.handle)));
9817                 return WERR_BADFID;
9818         }
9819
9820         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9821                 return WERR_BADFID;
9822         }
9823
9824         result = winreg_enum_printer_key_internal(p->mem_ctx,
9825                                          get_session_info_system(),
9826                                          p->msg_ctx,
9827                                          lp_const_servicename(snum),
9828                                          r->in.key_name,
9829                                          &num_keys,
9830                                          &array);
9831         if (!W_ERROR_IS_OK(result)) {
9832                 goto done;
9833         }
9834
9835         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9836                 result = WERR_NOMEM;
9837                 goto done;
9838         }
9839
9840         *r->out._ndr_size = r->in.offered / 2;
9841         *r->out.needed = blob.length;
9842
9843         if (r->in.offered < *r->out.needed) {
9844                 result = WERR_MORE_DATA;
9845         } else {
9846                 result = WERR_OK;
9847                 r->out.key_buffer->string_array = array;
9848         }
9849
9850  done:
9851         if (!W_ERROR_IS_OK(result)) {
9852                 TALLOC_FREE(array);
9853                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9854                         *r->out.needed = 0;
9855                 }
9856         }
9857
9858         return result;
9859 }
9860
9861 /****************************************************************
9862  _spoolss_DeletePrinterKey
9863 ****************************************************************/
9864
9865 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9866                                  struct spoolss_DeletePrinterKey *r)
9867 {
9868         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9869         int                     snum=0;
9870         WERROR                  status;
9871         const char *printer;
9872         struct dcerpc_binding_handle *b;
9873         TALLOC_CTX *tmp_ctx;
9874
9875         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9876
9877         if (!Printer) {
9878                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9879                         OUR_HANDLE(r->in.handle)));
9880                 return WERR_BADFID;
9881         }
9882
9883         /* if keyname == NULL, return error */
9884         if ( !r->in.key_name )
9885                 return WERR_INVALID_PARAM;
9886
9887         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9888                 return WERR_BADFID;
9889         }
9890
9891         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9892                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9893                         "printer properties change denied by handle\n"));
9894                 return WERR_ACCESS_DENIED;
9895         }
9896
9897         printer = lp_const_servicename(snum);
9898
9899         tmp_ctx = talloc_new(p->mem_ctx);
9900         if (!tmp_ctx) {
9901                 return WERR_NOMEM;
9902         }
9903
9904         status = winreg_printer_binding_handle(tmp_ctx,
9905                                                get_session_info_system(),
9906                                                p->msg_ctx,
9907                                                &b);
9908         if (!W_ERROR_IS_OK(status)) {
9909                 goto done;
9910         }
9911
9912         /* delete the key and all subkeys */
9913         status = winreg_delete_printer_key(tmp_ctx, b,
9914                                            printer,
9915                                            r->in.key_name);
9916         if (W_ERROR_IS_OK(status)) {
9917                 status = winreg_printer_update_changeid(tmp_ctx, b,
9918                                                         printer);
9919         }
9920
9921 done:
9922         talloc_free(tmp_ctx);
9923         return status;
9924 }
9925
9926 /****************************************************************
9927  _spoolss_EnumPrinterDataEx
9928 ****************************************************************/
9929
9930 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9931                                   struct spoolss_EnumPrinterDataEx *r)
9932 {
9933         uint32_t        count = 0;
9934         struct spoolss_PrinterEnumValues *info = NULL;
9935         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9936         int             snum;
9937         WERROR          result;
9938
9939         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9940
9941         *r->out.count = 0;
9942         *r->out.needed = 0;
9943         *r->out.info = NULL;
9944
9945         if (!Printer) {
9946                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9947                         OUR_HANDLE(r->in.handle)));
9948                 return WERR_BADFID;
9949         }
9950
9951         /*
9952          * first check for a keyname of NULL or "".  Win2k seems to send
9953          * this a lot and we should send back WERR_INVALID_PARAM
9954          * no need to spend time looking up the printer in this case.
9955          * --jerry
9956          */
9957
9958         if (!strlen(r->in.key_name)) {
9959                 result = WERR_INVALID_PARAM;
9960                 goto done;
9961         }
9962
9963         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9964                 return WERR_BADFID;
9965         }
9966
9967         /* now look for a match on the key name */
9968         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9969                                             get_session_info_system(),
9970                                             p->msg_ctx,
9971                                             lp_const_servicename(snum),
9972                                             r->in.key_name,
9973                                             &count,
9974                                             &info);
9975         if (!W_ERROR_IS_OK(result)) {
9976                 goto done;
9977         }
9978
9979 #if 0 /* FIXME - gd */
9980         /* housekeeping information in the reply */
9981
9982         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9983          * the hand marshalled container size is a multiple
9984          * of 4 bytes for RPC alignment.
9985          */
9986
9987         if (needed % 4) {
9988                 needed += 4-(needed % 4);
9989         }
9990 #endif
9991         *r->out.count   = count;
9992         *r->out.info    = info;
9993
9994  done:
9995         if (!W_ERROR_IS_OK(result)) {
9996                 return result;
9997         }
9998
9999         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10000                                                spoolss_EnumPrinterDataEx,
10001                                                *r->out.info,
10002                                                *r->out.count);
10003         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10004         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10005
10006         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10007 }
10008
10009 /****************************************************************************
10010 ****************************************************************************/
10011
10012 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10013                                                  const char *servername,
10014                                                  const char *environment,
10015                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
10016 {
10017         WERROR werr;
10018         char *path = NULL;
10019
10020         werr = compose_spoolss_server_path(mem_ctx,
10021                                            servername,
10022                                            environment,
10023                                            SPOOLSS_PRTPROCS_PATH,
10024                                            &path);
10025         if (!W_ERROR_IS_OK(werr)) {
10026                 return werr;
10027         }
10028
10029         DEBUG(4,("print processor directory: [%s]\n", path));
10030
10031         r->directory_name = path;
10032
10033         return WERR_OK;
10034 }
10035
10036 /****************************************************************
10037  _spoolss_GetPrintProcessorDirectory
10038 ****************************************************************/
10039
10040 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10041                                            struct spoolss_GetPrintProcessorDirectory *r)
10042 {
10043         WERROR result;
10044         char *prnproc_share = NULL;
10045         bool prnproc_share_exists = false;
10046         int snum;
10047
10048         /* that's an [in out] buffer */
10049
10050         if (!r->in.buffer && (r->in.offered != 0)) {
10051                 return WERR_INVALID_PARAM;
10052         }
10053
10054         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10055                 r->in.level));
10056
10057         *r->out.needed = 0;
10058
10059         /* r->in.level is ignored */
10060
10061         /* We always should reply with a local print processor directory so that
10062          * users are not forced to have a [prnproc$] share on the Samba spoolss
10063          * server, if users decide to do so, lets announce it though - Guenther */
10064
10065         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10066         if (!prnproc_share) {
10067                 return WERR_NOMEM;
10068         }
10069         if (snum != -1) {
10070                 prnproc_share_exists = true;
10071         }
10072
10073         result = getprintprocessordirectory_level_1(p->mem_ctx,
10074                                                     prnproc_share_exists ? r->in.server : NULL,
10075                                                     r->in.environment,
10076                                                     &r->out.info->info1);
10077         if (!W_ERROR_IS_OK(result)) {
10078                 TALLOC_FREE(r->out.info);
10079                 return result;
10080         }
10081
10082         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10083                                                                                    r->out.info, r->in.level);
10084         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10085
10086         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10087 }
10088
10089 /*******************************************************************
10090  ********************************************************************/
10091
10092 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10093                                const char *dllname)
10094 {
10095         enum ndr_err_code ndr_err;
10096         struct spoolss_MonitorUi ui;
10097
10098         ui.dll_name = dllname;
10099
10100         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10101                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10102         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10103                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10104         }
10105         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10106 }
10107
10108 /*******************************************************************
10109  Streams the monitor UI DLL name in UNICODE
10110 *******************************************************************/
10111
10112 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10113                                struct security_token *token, DATA_BLOB *in,
10114                                DATA_BLOB *out, uint32_t *needed)
10115 {
10116         const char *dllname = "tcpmonui.dll";
10117
10118         *needed = (strlen(dllname)+1) * 2;
10119
10120         if (out->length < *needed) {
10121                 return WERR_INSUFFICIENT_BUFFER;
10122         }
10123
10124         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10125                 return WERR_NOMEM;
10126         }
10127
10128         return WERR_OK;
10129 }
10130
10131 /*******************************************************************
10132  ********************************************************************/
10133
10134 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10135                              struct spoolss_PortData1 *port1,
10136                              const DATA_BLOB *buf)
10137 {
10138         enum ndr_err_code ndr_err;
10139         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10140                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10141         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10142                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10143         }
10144         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10145 }
10146
10147 /*******************************************************************
10148  ********************************************************************/
10149
10150 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10151                              struct spoolss_PortData2 *port2,
10152                              const DATA_BLOB *buf)
10153 {
10154         enum ndr_err_code ndr_err;
10155         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10156                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10157         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10158                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10159         }
10160         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10161 }
10162
10163 /*******************************************************************
10164  Create a new TCP/IP port
10165 *******************************************************************/
10166
10167 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10168                              struct security_token *token, DATA_BLOB *in,
10169                              DATA_BLOB *out, uint32_t *needed)
10170 {
10171         struct spoolss_PortData1 port1;
10172         struct spoolss_PortData2 port2;
10173         char *device_uri = NULL;
10174         uint32_t version;
10175
10176         const char *portname;
10177         const char *hostaddress;
10178         const char *queue;
10179         uint32_t port_number;
10180         uint32_t protocol;
10181
10182         /* peek for spoolss_PortData version */
10183
10184         if (!in || (in->length < (128 + 4))) {
10185                 return WERR_GENERAL_FAILURE;
10186         }
10187
10188         version = IVAL(in->data, 128);
10189
10190         switch (version) {
10191                 case 1:
10192                         ZERO_STRUCT(port1);
10193
10194                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10195                                 return WERR_NOMEM;
10196                         }
10197
10198                         portname        = port1.portname;
10199                         hostaddress     = port1.hostaddress;
10200                         queue           = port1.queue;
10201                         protocol        = port1.protocol;
10202                         port_number     = port1.port_number;
10203
10204                         break;
10205                 case 2:
10206                         ZERO_STRUCT(port2);
10207
10208                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10209                                 return WERR_NOMEM;
10210                         }
10211
10212                         portname        = port2.portname;
10213                         hostaddress     = port2.hostaddress;
10214                         queue           = port2.queue;
10215                         protocol        = port2.protocol;
10216                         port_number     = port2.port_number;
10217
10218                         break;
10219                 default:
10220                         DEBUG(1,("xcvtcp_addport: "
10221                                 "unknown version of port_data: %d\n", version));
10222                         return WERR_UNKNOWN_PORT;
10223         }
10224
10225         /* create the device URI and call the add_port_hook() */
10226
10227         switch (protocol) {
10228         case PROTOCOL_RAWTCP_TYPE:
10229                 device_uri = talloc_asprintf(mem_ctx,
10230                                 "socket://%s:%d/", hostaddress,
10231                                 port_number);
10232                 break;
10233
10234         case PROTOCOL_LPR_TYPE:
10235                 device_uri = talloc_asprintf(mem_ctx,
10236                         "lpr://%s/%s", hostaddress, queue );
10237                 break;
10238
10239         default:
10240                 return WERR_UNKNOWN_PORT;
10241         }
10242
10243         if (!device_uri) {
10244                 return WERR_NOMEM;
10245         }
10246
10247         return add_port_hook(mem_ctx, token, portname, device_uri);
10248 }
10249
10250 /*******************************************************************
10251 *******************************************************************/
10252
10253 struct xcv_api_table xcvtcp_cmds[] = {
10254         { "MonitorUI",  xcvtcp_monitorui },
10255         { "AddPort",    xcvtcp_addport},
10256         { NULL,         NULL }
10257 };
10258
10259 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10260                                      struct security_token *token, const char *command,
10261                                      DATA_BLOB *inbuf,
10262                                      DATA_BLOB *outbuf,
10263                                      uint32_t *needed )
10264 {
10265         int i;
10266
10267         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10268
10269         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10270                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10271                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10272         }
10273
10274         return WERR_BADFUNC;
10275 }
10276
10277 /*******************************************************************
10278 *******************************************************************/
10279 #if 0   /* don't support management using the "Local Port" monitor */
10280
10281 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10282                                  struct security_token *token, DATA_BLOB *in,
10283                                  DATA_BLOB *out, uint32_t *needed)
10284 {
10285         const char *dllname = "localui.dll";
10286
10287         *needed = (strlen(dllname)+1) * 2;
10288
10289         if (out->length < *needed) {
10290                 return WERR_INSUFFICIENT_BUFFER;
10291         }
10292
10293         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10294                 return WERR_NOMEM;
10295         }
10296
10297         return WERR_OK;
10298 }
10299
10300 /*******************************************************************
10301 *******************************************************************/
10302
10303 struct xcv_api_table xcvlocal_cmds[] = {
10304         { "MonitorUI",  xcvlocal_monitorui },
10305         { NULL,         NULL }
10306 };
10307 #else
10308 struct xcv_api_table xcvlocal_cmds[] = {
10309         { NULL,         NULL }
10310 };
10311 #endif
10312
10313
10314
10315 /*******************************************************************
10316 *******************************************************************/
10317
10318 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10319                                        struct security_token *token, const char *command,
10320                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10321                                        uint32_t *needed)
10322 {
10323         int i;
10324
10325         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10326
10327         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10328                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10329                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10330         }
10331         return WERR_BADFUNC;
10332 }
10333
10334 /****************************************************************
10335  _spoolss_XcvData
10336 ****************************************************************/
10337
10338 WERROR _spoolss_XcvData(struct pipes_struct *p,
10339                         struct spoolss_XcvData *r)
10340 {
10341         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10342         DATA_BLOB out_data = data_blob_null;
10343         WERROR werror;
10344
10345         if (!Printer) {
10346                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10347                         OUR_HANDLE(r->in.handle)));
10348                 return WERR_BADFID;
10349         }
10350
10351         /* Has to be a handle to the TCP/IP port monitor */
10352
10353         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10354                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10355                 return WERR_BADFID;
10356         }
10357
10358         /* requires administrative access to the server */
10359
10360         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10361                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10362                 return WERR_ACCESS_DENIED;
10363         }
10364
10365         /* Allocate the outgoing buffer */
10366
10367         if (r->in.out_data_size) {
10368                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10369                 if (out_data.data == NULL) {
10370                         return WERR_NOMEM;
10371                 }
10372         }
10373
10374         switch ( Printer->printer_type ) {
10375         case SPLHND_PORTMON_TCP:
10376                 werror = process_xcvtcp_command(p->mem_ctx,
10377                                                 p->session_info->security_token,
10378                                                 r->in.function_name,
10379                                                 &r->in.in_data, &out_data,
10380                                                 r->out.needed);
10381                 break;
10382         case SPLHND_PORTMON_LOCAL:
10383                 werror = process_xcvlocal_command(p->mem_ctx,
10384                                                   p->session_info->security_token,
10385                                                   r->in.function_name,
10386                                                   &r->in.in_data, &out_data,
10387                                                   r->out.needed);
10388                 break;
10389         default:
10390                 werror = WERR_INVALID_PRINT_MONITOR;
10391         }
10392
10393         if (!W_ERROR_IS_OK(werror)) {
10394                 return werror;
10395         }
10396
10397         *r->out.status_code = 0;
10398
10399         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10400                 memcpy(r->out.out_data, out_data.data,
10401                         MIN(r->in.out_data_size, out_data.length));
10402         }
10403
10404         return WERR_OK;
10405 }
10406
10407 /****************************************************************
10408  _spoolss_AddPrintProcessor
10409 ****************************************************************/
10410
10411 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10412                                   struct spoolss_AddPrintProcessor *r)
10413 {
10414         /* for now, just indicate success and ignore the add.  We'll
10415            automatically set the winprint processor for printer
10416            entries later.  Used to debug the LexMark Optra S 1855 PCL
10417            driver --jerry */
10418
10419         return WERR_OK;
10420 }
10421
10422 /****************************************************************
10423  _spoolss_AddPort
10424 ****************************************************************/
10425
10426 WERROR _spoolss_AddPort(struct pipes_struct *p,
10427                         struct spoolss_AddPort *r)
10428 {
10429         /* do what w2k3 does */
10430
10431         return WERR_NOT_SUPPORTED;
10432 }
10433
10434 /****************************************************************
10435  _spoolss_GetPrinterDriver
10436 ****************************************************************/
10437
10438 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10439                                  struct spoolss_GetPrinterDriver *r)
10440 {
10441         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10442         return WERR_NOT_SUPPORTED;
10443 }
10444
10445 /****************************************************************
10446  _spoolss_ReadPrinter
10447 ****************************************************************/
10448
10449 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10450                             struct spoolss_ReadPrinter *r)
10451 {
10452         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10453         return WERR_NOT_SUPPORTED;
10454 }
10455
10456 /****************************************************************
10457  _spoolss_WaitForPrinterChange
10458 ****************************************************************/
10459
10460 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10461                                      struct spoolss_WaitForPrinterChange *r)
10462 {
10463         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10464         return WERR_NOT_SUPPORTED;
10465 }
10466
10467 /****************************************************************
10468  _spoolss_ConfigurePort
10469 ****************************************************************/
10470
10471 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10472                               struct spoolss_ConfigurePort *r)
10473 {
10474         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10475         return WERR_NOT_SUPPORTED;
10476 }
10477
10478 /****************************************************************
10479  _spoolss_DeletePort
10480 ****************************************************************/
10481
10482 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10483                            struct spoolss_DeletePort *r)
10484 {
10485         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10486         return WERR_NOT_SUPPORTED;
10487 }
10488
10489 /****************************************************************
10490  _spoolss_CreatePrinterIC
10491 ****************************************************************/
10492
10493 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10494                                 struct spoolss_CreatePrinterIC *r)
10495 {
10496         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10497         return WERR_NOT_SUPPORTED;
10498 }
10499
10500 /****************************************************************
10501  _spoolss_PlayGDIScriptOnPrinterIC
10502 ****************************************************************/
10503
10504 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10505                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10506 {
10507         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10508         return WERR_NOT_SUPPORTED;
10509 }
10510
10511 /****************************************************************
10512  _spoolss_DeletePrinterIC
10513 ****************************************************************/
10514
10515 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10516                                 struct spoolss_DeletePrinterIC *r)
10517 {
10518         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10519         return WERR_NOT_SUPPORTED;
10520 }
10521
10522 /****************************************************************
10523  _spoolss_AddPrinterConnection
10524 ****************************************************************/
10525
10526 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10527                                      struct spoolss_AddPrinterConnection *r)
10528 {
10529         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10530         return WERR_NOT_SUPPORTED;
10531 }
10532
10533 /****************************************************************
10534  _spoolss_DeletePrinterConnection
10535 ****************************************************************/
10536
10537 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10538                                         struct spoolss_DeletePrinterConnection *r)
10539 {
10540         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10541         return WERR_NOT_SUPPORTED;
10542 }
10543
10544 /****************************************************************
10545  _spoolss_PrinterMessageBox
10546 ****************************************************************/
10547
10548 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10549                                   struct spoolss_PrinterMessageBox *r)
10550 {
10551         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10552         return WERR_NOT_SUPPORTED;
10553 }
10554
10555 /****************************************************************
10556  _spoolss_AddMonitor
10557 ****************************************************************/
10558
10559 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10560                            struct spoolss_AddMonitor *r)
10561 {
10562         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10563         return WERR_NOT_SUPPORTED;
10564 }
10565
10566 /****************************************************************
10567  _spoolss_DeleteMonitor
10568 ****************************************************************/
10569
10570 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10571                               struct spoolss_DeleteMonitor *r)
10572 {
10573         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10574         return WERR_NOT_SUPPORTED;
10575 }
10576
10577 /****************************************************************
10578  _spoolss_DeletePrintProcessor
10579 ****************************************************************/
10580
10581 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10582                                      struct spoolss_DeletePrintProcessor *r)
10583 {
10584         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10585         return WERR_NOT_SUPPORTED;
10586 }
10587
10588 /****************************************************************
10589  _spoolss_AddPrintProvidor
10590 ****************************************************************/
10591
10592 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10593                                  struct spoolss_AddPrintProvidor *r)
10594 {
10595         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10596         return WERR_NOT_SUPPORTED;
10597 }
10598
10599 /****************************************************************
10600  _spoolss_DeletePrintProvidor
10601 ****************************************************************/
10602
10603 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10604                                     struct spoolss_DeletePrintProvidor *r)
10605 {
10606         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10607         return WERR_NOT_SUPPORTED;
10608 }
10609
10610 /****************************************************************
10611  _spoolss_FindFirstPrinterChangeNotification
10612 ****************************************************************/
10613
10614 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10615                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10616 {
10617         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10618         return WERR_NOT_SUPPORTED;
10619 }
10620
10621 /****************************************************************
10622  _spoolss_FindNextPrinterChangeNotification
10623 ****************************************************************/
10624
10625 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10626                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10627 {
10628         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10629         return WERR_NOT_SUPPORTED;
10630 }
10631
10632 /****************************************************************
10633  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10634 ****************************************************************/
10635
10636 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10637                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10638 {
10639         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10640         return WERR_NOT_SUPPORTED;
10641 }
10642
10643 /****************************************************************
10644  _spoolss_ReplyOpenPrinter
10645 ****************************************************************/
10646
10647 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10648                                  struct spoolss_ReplyOpenPrinter *r)
10649 {
10650         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10651         return WERR_NOT_SUPPORTED;
10652 }
10653
10654 /****************************************************************
10655  _spoolss_RouterReplyPrinter
10656 ****************************************************************/
10657
10658 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10659                                    struct spoolss_RouterReplyPrinter *r)
10660 {
10661         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10662         return WERR_NOT_SUPPORTED;
10663 }
10664
10665 /****************************************************************
10666  _spoolss_ReplyClosePrinter
10667 ****************************************************************/
10668
10669 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10670                                   struct spoolss_ReplyClosePrinter *r)
10671 {
10672         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10673         return WERR_NOT_SUPPORTED;
10674 }
10675
10676 /****************************************************************
10677  _spoolss_AddPortEx
10678 ****************************************************************/
10679
10680 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10681                           struct spoolss_AddPortEx *r)
10682 {
10683         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10684         return WERR_NOT_SUPPORTED;
10685 }
10686
10687 /****************************************************************
10688  _spoolss_RouterFindFirstPrinterChangeNotification
10689 ****************************************************************/
10690
10691 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10692                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10693 {
10694         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10695         return WERR_NOT_SUPPORTED;
10696 }
10697
10698 /****************************************************************
10699  _spoolss_SpoolerInit
10700 ****************************************************************/
10701
10702 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10703                             struct spoolss_SpoolerInit *r)
10704 {
10705         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10706         return WERR_NOT_SUPPORTED;
10707 }
10708
10709 /****************************************************************
10710  _spoolss_ResetPrinterEx
10711 ****************************************************************/
10712
10713 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10714                                struct spoolss_ResetPrinterEx *r)
10715 {
10716         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10717         return WERR_NOT_SUPPORTED;
10718 }
10719
10720 /****************************************************************
10721  _spoolss_RouterReplyPrinterEx
10722 ****************************************************************/
10723
10724 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10725                                      struct spoolss_RouterReplyPrinterEx *r)
10726 {
10727         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10728         return WERR_NOT_SUPPORTED;
10729 }
10730
10731 /****************************************************************
10732  _spoolss_44
10733 ****************************************************************/
10734
10735 WERROR _spoolss_44(struct pipes_struct *p,
10736                    struct spoolss_44 *r)
10737 {
10738         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10739         return WERR_NOT_SUPPORTED;
10740 }
10741
10742 /****************************************************************
10743  _spoolss_SetPort
10744 ****************************************************************/
10745
10746 WERROR _spoolss_SetPort(struct pipes_struct *p,
10747                         struct spoolss_SetPort *r)
10748 {
10749         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10750         return WERR_NOT_SUPPORTED;
10751 }
10752
10753 /****************************************************************
10754  _spoolss_4a
10755 ****************************************************************/
10756
10757 WERROR _spoolss_4a(struct pipes_struct *p,
10758                    struct spoolss_4a *r)
10759 {
10760         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10761         return WERR_NOT_SUPPORTED;
10762 }
10763
10764 /****************************************************************
10765  _spoolss_4b
10766 ****************************************************************/
10767
10768 WERROR _spoolss_4b(struct pipes_struct *p,
10769                    struct spoolss_4b *r)
10770 {
10771         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10772         return WERR_NOT_SUPPORTED;
10773 }
10774
10775 /****************************************************************
10776  _spoolss_4c
10777 ****************************************************************/
10778
10779 WERROR _spoolss_4c(struct pipes_struct *p,
10780                    struct spoolss_4c *r)
10781 {
10782         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10783         return WERR_NOT_SUPPORTED;
10784 }
10785
10786 /****************************************************************
10787  _spoolss_53
10788 ****************************************************************/
10789
10790 WERROR _spoolss_53(struct pipes_struct *p,
10791                    struct spoolss_53 *r)
10792 {
10793         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10794         return WERR_NOT_SUPPORTED;
10795 }
10796
10797 /****************************************************************
10798  _spoolss_AddPerMachineConnection
10799 ****************************************************************/
10800
10801 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10802                                         struct spoolss_AddPerMachineConnection *r)
10803 {
10804         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10805         return WERR_NOT_SUPPORTED;
10806 }
10807
10808 /****************************************************************
10809  _spoolss_DeletePerMachineConnection
10810 ****************************************************************/
10811
10812 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10813                                            struct spoolss_DeletePerMachineConnection *r)
10814 {
10815         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10816         return WERR_NOT_SUPPORTED;
10817 }
10818
10819 /****************************************************************
10820  _spoolss_EnumPerMachineConnections
10821 ****************************************************************/
10822
10823 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10824                                           struct spoolss_EnumPerMachineConnections *r)
10825 {
10826         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10827         return WERR_NOT_SUPPORTED;
10828 }
10829
10830 /****************************************************************
10831  _spoolss_5a
10832 ****************************************************************/
10833
10834 WERROR _spoolss_5a(struct pipes_struct *p,
10835                    struct spoolss_5a *r)
10836 {
10837         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10838         return WERR_NOT_SUPPORTED;
10839 }
10840
10841 /****************************************************************
10842  _spoolss_5b
10843 ****************************************************************/
10844
10845 WERROR _spoolss_5b(struct pipes_struct *p,
10846                    struct spoolss_5b *r)
10847 {
10848         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10849         return WERR_NOT_SUPPORTED;
10850 }
10851
10852 /****************************************************************
10853  _spoolss_5c
10854 ****************************************************************/
10855
10856 WERROR _spoolss_5c(struct pipes_struct *p,
10857                    struct spoolss_5c *r)
10858 {
10859         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10860         return WERR_NOT_SUPPORTED;
10861 }
10862
10863 /****************************************************************
10864  _spoolss_5d
10865 ****************************************************************/
10866
10867 WERROR _spoolss_5d(struct pipes_struct *p,
10868                    struct spoolss_5d *r)
10869 {
10870         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10871         return WERR_NOT_SUPPORTED;
10872 }
10873
10874 /****************************************************************
10875  _spoolss_5e
10876 ****************************************************************/
10877
10878 WERROR _spoolss_5e(struct pipes_struct *p,
10879                    struct spoolss_5e *r)
10880 {
10881         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10882         return WERR_NOT_SUPPORTED;
10883 }
10884
10885 /****************************************************************
10886  _spoolss_5f
10887 ****************************************************************/
10888
10889 WERROR _spoolss_5f(struct pipes_struct *p,
10890                    struct spoolss_5f *r)
10891 {
10892         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10893         return WERR_NOT_SUPPORTED;
10894 }
10895
10896 /****************************************************************
10897  _spoolss_60
10898 ****************************************************************/
10899
10900 WERROR _spoolss_60(struct pipes_struct *p,
10901                    struct spoolss_60 *r)
10902 {
10903         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10904         return WERR_NOT_SUPPORTED;
10905 }
10906
10907 /****************************************************************
10908  _spoolss_RpcSendRecvBidiData
10909 ****************************************************************/
10910
10911 WERROR _spoolss_RpcSendRecvBidiData(struct pipes_struct *p,
10912                                     struct spoolss_RpcSendRecvBidiData *r)
10913 {
10914         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10915         return WERR_NOT_SUPPORTED;
10916 }
10917
10918 /****************************************************************
10919  _spoolss_62
10920 ****************************************************************/
10921
10922 WERROR _spoolss_62(struct pipes_struct *p,
10923                    struct spoolss_62 *r)
10924 {
10925         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10926         return WERR_NOT_SUPPORTED;
10927 }
10928
10929 /****************************************************************
10930  _spoolss_63
10931 ****************************************************************/
10932
10933 WERROR _spoolss_63(struct pipes_struct *p,
10934                    struct spoolss_63 *r)
10935 {
10936         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10937         return WERR_NOT_SUPPORTED;
10938 }
10939
10940 /****************************************************************
10941  _spoolss_64
10942 ****************************************************************/
10943
10944 WERROR _spoolss_64(struct pipes_struct *p,
10945                    struct spoolss_64 *r)
10946 {
10947         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10948         return WERR_NOT_SUPPORTED;
10949 }
10950
10951 /****************************************************************
10952  _spoolss_65
10953 ****************************************************************/
10954
10955 WERROR _spoolss_65(struct pipes_struct *p,
10956                    struct spoolss_65 *r)
10957 {
10958         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10959         return WERR_NOT_SUPPORTED;
10960 }
10961
10962 /****************************************************************
10963  _spoolss_GetCorePrinterDrivers
10964 ****************************************************************/
10965
10966 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10967                                       struct spoolss_GetCorePrinterDrivers *r)
10968 {
10969         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10970         return WERR_NOT_SUPPORTED;
10971 }
10972
10973 /****************************************************************
10974  _spoolss_67
10975 ****************************************************************/
10976
10977 WERROR _spoolss_67(struct pipes_struct *p,
10978                    struct spoolss_67 *r)
10979 {
10980         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10981         return WERR_NOT_SUPPORTED;
10982 }
10983
10984 /****************************************************************
10985  _spoolss_GetPrinterDriverPackagePath
10986 ****************************************************************/
10987
10988 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10989                                             struct spoolss_GetPrinterDriverPackagePath *r)
10990 {
10991         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10992         return WERR_NOT_SUPPORTED;
10993 }
10994
10995 /****************************************************************
10996  _spoolss_69
10997 ****************************************************************/
10998
10999 WERROR _spoolss_69(struct pipes_struct *p,
11000                    struct spoolss_69 *r)
11001 {
11002         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11003         return WERR_NOT_SUPPORTED;
11004 }
11005
11006 /****************************************************************
11007  _spoolss_6a
11008 ****************************************************************/
11009
11010 WERROR _spoolss_6a(struct pipes_struct *p,
11011                    struct spoolss_6a *r)
11012 {
11013         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11014         return WERR_NOT_SUPPORTED;
11015 }
11016
11017 /****************************************************************
11018  _spoolss_6b
11019 ****************************************************************/
11020
11021 WERROR _spoolss_6b(struct pipes_struct *p,
11022                    struct spoolss_6b *r)
11023 {
11024         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11025         return WERR_NOT_SUPPORTED;
11026 }
11027
11028 /****************************************************************
11029  _spoolss_6c
11030 ****************************************************************/
11031
11032 WERROR _spoolss_6c(struct pipes_struct *p,
11033                    struct spoolss_6c *r)
11034 {
11035         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11036         return WERR_NOT_SUPPORTED;
11037 }
11038
11039 /****************************************************************
11040  _spoolss_6d
11041 ****************************************************************/
11042
11043 WERROR _spoolss_6d(struct pipes_struct *p,
11044                    struct spoolss_6d *r)
11045 {
11046         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11047         return WERR_NOT_SUPPORTED;
11048 }
11049
11050 /****************************************************************
11051  _spoolss_RpcGetJobNamedPropertyValue
11052 ****************************************************************/
11053
11054 WERROR _spoolss_RpcGetJobNamedPropertyValue(struct pipes_struct *p,
11055                                             struct spoolss_RpcGetJobNamedPropertyValue *r)
11056 {
11057         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11058         return WERR_NOT_SUPPORTED;
11059 }
11060
11061 /****************************************************************
11062  _spoolss_RpcSetJobNamedProperty
11063 ****************************************************************/
11064
11065 WERROR _spoolss_RpcSetJobNamedProperty(struct pipes_struct *p,
11066                                        struct spoolss_RpcSetJobNamedProperty *r)
11067 {
11068         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11069         return WERR_NOT_SUPPORTED;
11070 }
11071
11072 /****************************************************************
11073  _spoolss_RpcDeleteJobNamedProperty
11074 ****************************************************************/
11075
11076 WERROR _spoolss_RpcDeleteJobNamedProperty(struct pipes_struct *p,
11077                                           struct spoolss_RpcDeleteJobNamedProperty *r)
11078 {
11079         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11080         return WERR_NOT_SUPPORTED;
11081 }
11082
11083 /****************************************************************
11084  _spoolss_RpcEnumJobNamedProperties
11085 ****************************************************************/
11086
11087 WERROR _spoolss_RpcEnumJobNamedProperties(struct pipes_struct *p,
11088                                           struct spoolss_RpcEnumJobNamedProperties *r)
11089 {
11090         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11091         return WERR_NOT_SUPPORTED;
11092 }