99e5eb2add1295805f01baa96cd894ccd3964e4e
[metze/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_t jobid; /* jobid in printing backend */
90         int printer_type;
91         const char *servername;
92         fstring sharename;
93         uint32_t type;
94         uint32_t access_granted;
95         struct {
96                 uint32_t flags;
97                 uint32_t options;
98                 fstring localmachine;
99                 uint32_t printerlocal;
100                 struct spoolss_NotifyOption *option;
101                 struct policy_handle cli_hnd;
102                 struct notify_back_channel *cli_chan;
103                 uint32_t 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_command(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_NOT_ENOUGH_MEMORY;
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_INVALID_HANDLE; /* 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_INVALID_HANDLE;
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_INVALID_HANDLE;
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_NOT_ENOUGH_MEMORY;
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         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
626         if (cache_key == NULL) {
627                 return WERR_NOT_ENOUGH_MEMORY;
628         }
629
630         /*
631          * With hundreds of printers, the "for" loop iterating all
632          * shares can be quite expensive, as it is done on every
633          * OpenPrinter. The loop maps "aprinter" to "sname", the
634          * result of which we cache in gencache.
635          */
636         if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
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                 gencache_set(cache_key, printer_not_found,
707                              time_mono(NULL) + 300);
708                 TALLOC_FREE(cache_key);
709                 DEBUGADD(4,("Printer not found\n"));
710                 return WERR_INVALID_PRINTER_NAME;
711         }
712
713         gencache_set(cache_key, sname, time_mono(NULL) + 300);
714         TALLOC_FREE(cache_key);
715
716         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
717
718         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
719
720         return WERR_OK;
721 }
722
723 /****************************************************************************
724  Find first available printer slot. creates a printer handle for you.
725  ****************************************************************************/
726
727 static WERROR open_printer_hnd(struct pipes_struct *p,
728                                struct policy_handle *hnd,
729                                const char *name,
730                                uint32_t access_granted)
731 {
732         struct printer_handle *new_printer;
733         WERROR result;
734
735         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
736
737         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
738         if (new_printer == NULL) {
739                 return WERR_NOT_ENOUGH_MEMORY;
740         }
741         talloc_set_destructor(new_printer, printer_entry_destructor);
742
743         /* This also steals the printer_handle on the policy_handle */
744         if (!create_policy_hnd(p, hnd, new_printer)) {
745                 TALLOC_FREE(new_printer);
746                 return WERR_INVALID_HANDLE;
747         }
748
749         /* Add to the internal list. */
750         DLIST_ADD(printers_list, new_printer);
751
752         new_printer->notify.option=NULL;
753
754         if (!set_printer_hnd_printertype(new_printer, name)) {
755                 close_printer_handle(p, hnd);
756                 return WERR_INVALID_HANDLE;
757         }
758
759         result = set_printer_hnd_name(p->mem_ctx,
760                                       get_session_info_system(),
761                                       p->msg_ctx,
762                                       new_printer, name);
763         if (!W_ERROR_IS_OK(result)) {
764                 close_printer_handle(p, hnd);
765                 return result;
766         }
767
768         new_printer->access_granted = access_granted;
769
770         DEBUG(5, ("%d printer handles active\n",
771                   (int)num_pipe_handles(p)));
772
773         return WERR_OK;
774 }
775
776 /***************************************************************************
777  check to see if the client motify handle is monitoring the notification
778  given by (notify_type, notify_field).
779  **************************************************************************/
780
781 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
782                                       uint16_t notify_field)
783 {
784         return true;
785 }
786
787 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
788                                 uint16_t notify_field)
789 {
790         struct spoolss_NotifyOption *option = p->notify.option;
791         uint32_t i, j;
792
793         /*
794          * Flags should always be zero when the change notify
795          * is registered by the client's spooler.  A user Win32 app
796          * might use the flags though instead of the NOTIFY_OPTION_INFO
797          * --jerry
798          */
799
800         if (!option) {
801                 return false;
802         }
803
804         if (p->notify.flags)
805                 return is_monitoring_event_flags(
806                         p->notify.flags, notify_type, notify_field);
807
808         for (i = 0; i < option->count; i++) {
809
810                 /* Check match for notify_type */
811
812                 if (option->types[i].type != notify_type)
813                         continue;
814
815                 /* Check match for field */
816
817                 for (j = 0; j < option->types[i].count; j++) {
818                         if (option->types[i].fields[j].field == notify_field) {
819                                 return true;
820                         }
821                 }
822         }
823
824         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
825                    p->servername, p->sharename, notify_type, notify_field));
826
827         return false;
828 }
829
830 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
831         _data->data.integer[0] = _integer; \
832         _data->data.integer[1] = 0;
833
834
835 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
836         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
837         if (!_data->data.string.string) {\
838                 _data->data.string.size = 0; \
839         } \
840         _data->data.string.size = strlen_m_term(_p) * 2;
841
842 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
843         _data->data.devmode.devmode = _devmode;
844
845 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
846                                    struct tm *t,
847                                    const char **pp,
848                                    uint32_t *plen)
849 {
850         struct spoolss_Time st;
851         uint32_t len = 16;
852         char *p;
853
854         if (!init_systemtime(&st, t)) {
855                 return;
856         }
857
858         p = talloc_array(mem_ctx, char, len);
859         if (!p) {
860                 return;
861         }
862
863         /*
864          * Systemtime must be linearized as a set of UINT16's.
865          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
866          */
867
868         SSVAL(p, 0, st.year);
869         SSVAL(p, 2, st.month);
870         SSVAL(p, 4, st.day_of_week);
871         SSVAL(p, 6, st.day);
872         SSVAL(p, 8, st.hour);
873         SSVAL(p, 10, st.minute);
874         SSVAL(p, 12, st.second);
875         SSVAL(p, 14, st.millisecond);
876
877         *pp = p;
878         *plen = len;
879 }
880
881 /* Convert a notification message to a struct spoolss_Notify */
882
883 static void notify_one_value(struct spoolss_notify_msg *msg,
884                              struct spoolss_Notify *data,
885                              TALLOC_CTX *mem_ctx)
886 {
887         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
888 }
889
890 static void notify_string(struct spoolss_notify_msg *msg,
891                           struct spoolss_Notify *data,
892                           TALLOC_CTX *mem_ctx)
893 {
894         /* The length of the message includes the trailing \0 */
895
896         data->data.string.size = msg->len * 2;
897         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
898         if (!data->data.string.string) {
899                 data->data.string.size = 0;
900                 return;
901         }
902 }
903
904 static void notify_system_time(struct spoolss_notify_msg *msg,
905                                struct spoolss_Notify *data,
906                                TALLOC_CTX *mem_ctx)
907 {
908         data->data.string.string = NULL;
909         data->data.string.size = 0;
910
911         if (msg->len != sizeof(time_t)) {
912                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
913                           msg->len));
914                 return;
915         }
916
917         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
918                                &data->data.string.string,
919                                &data->data.string.size);
920 }
921
922 struct notify2_message_table {
923         const char *name;
924         void (*fn)(struct spoolss_notify_msg *msg,
925                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
926 };
927
928 static struct notify2_message_table printer_notify_table[] = {
929         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
930         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
931         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
932         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
933         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
934         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
935         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
936         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
937         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
938         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
939         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
940         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
941         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
942         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
943         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
944         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
945         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
946         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
947         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
948 };
949
950 static struct notify2_message_table job_notify_table[] = {
951         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
952         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
953         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
954         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
955         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
956         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
957         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
958         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
959         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
960         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
961         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
962         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
963         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
964         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
965         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
966         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
967         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
968         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
969         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
970         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
971         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
972         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
973         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
974         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
975 };
976
977
978 /***********************************************************************
979  Allocate talloc context for container object
980  **********************************************************************/
981
982 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
983 {
984         if ( !ctr )
985                 return;
986
987         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
988
989         return;
990 }
991
992 /***********************************************************************
993  release all allocated memory and zero out structure
994  **********************************************************************/
995
996 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
997 {
998         if ( !ctr )
999                 return;
1000
1001         if ( ctr->ctx )
1002                 talloc_destroy(ctr->ctx);
1003
1004         ZERO_STRUCTP(ctr);
1005
1006         return;
1007 }
1008
1009 /***********************************************************************
1010  **********************************************************************/
1011
1012 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1013 {
1014         if ( !ctr )
1015                 return NULL;
1016
1017         return ctr->ctx;
1018 }
1019
1020 /***********************************************************************
1021  **********************************************************************/
1022
1023 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1024 {
1025         if ( !ctr || !ctr->msg_groups )
1026                 return NULL;
1027
1028         if ( idx >= ctr->num_groups )
1029                 return NULL;
1030
1031         return &ctr->msg_groups[idx];
1032
1033 }
1034
1035 /***********************************************************************
1036  How many groups of change messages do we have ?
1037  **********************************************************************/
1038
1039 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1040 {
1041         if ( !ctr )
1042                 return 0;
1043
1044         return ctr->num_groups;
1045 }
1046
1047 /***********************************************************************
1048  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1049  **********************************************************************/
1050
1051 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1052 {
1053         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1054         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1055         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1056         int                             i, new_slot;
1057
1058         if ( !ctr || !msg )
1059                 return 0;
1060
1061         /* loop over all groups looking for a matching printer name */
1062
1063         for ( i=0; i<ctr->num_groups; i++ ) {
1064                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1065                         break;
1066         }
1067
1068         /* add a new group? */
1069
1070         if ( i == ctr->num_groups ) {
1071                 ctr->num_groups++;
1072
1073                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1074                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1075                         return 0;
1076                 }
1077                 ctr->msg_groups = groups;
1078
1079                 /* clear the new entry and set the printer name */
1080
1081                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1082                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1083         }
1084
1085         /* add the change messages; 'i' is the correct index now regardless */
1086
1087         msg_grp = &ctr->msg_groups[i];
1088
1089         msg_grp->num_msgs++;
1090
1091         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1092                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1093                 return 0;
1094         }
1095         msg_grp->msgs = msg_list;
1096
1097         new_slot = msg_grp->num_msgs-1;
1098         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1099
1100         /* need to allocate own copy of data */
1101
1102         if ( msg->len != 0 )
1103                 msg_grp->msgs[new_slot].notify.data = (char *)
1104                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1105
1106         return ctr->num_groups;
1107 }
1108
1109 static void construct_info_data(struct spoolss_Notify *info_data,
1110                                 enum spoolss_NotifyType type,
1111                                 uint16_t field, int id);
1112
1113 /***********************************************************************
1114  Send a change notication message on all handles which have a call
1115  back registered
1116  **********************************************************************/
1117
1118 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1119                                   struct printer_handle *prn_hnd,
1120                                   SPOOLSS_NOTIFY_MSG *messages,
1121                                   uint32_t num_msgs,
1122                                   struct spoolss_Notify **_notifies,
1123                                   int *_count)
1124 {
1125         struct spoolss_Notify *notifies;
1126         SPOOLSS_NOTIFY_MSG *msg;
1127         int count = 0;
1128         uint32_t id;
1129         int i;
1130
1131         notifies = talloc_zero_array(mem_ctx,
1132                                      struct spoolss_Notify, num_msgs);
1133         if (!notifies) {
1134                 return ENOMEM;
1135         }
1136
1137         for (i = 0; i < num_msgs; i++) {
1138
1139                 msg = &messages[i];
1140
1141                 /* Are we monitoring this event? */
1142
1143                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1144                         continue;
1145                 }
1146
1147                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1148                            "for printer [%s]\n",
1149                            msg->type, msg->field, prn_hnd->sharename));
1150
1151                 /*
1152                  * if the is a printer notification handle and not a job
1153                  * notification type, then set the id to 0.
1154                  * Otherwise just use what was specified in the message.
1155                  *
1156                  * When registering change notification on a print server
1157                  * handle we always need to send back the id (snum) matching
1158                  * the printer for which the change took place.
1159                  * For change notify registered on a printer handle,
1160                  * this does not matter and the id should be 0.
1161                  *
1162                  * --jerry
1163                  */
1164
1165                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1166                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1167                         id = 0;
1168                 } else {
1169                         id = msg->id;
1170                 }
1171
1172                 /* Convert unix jobid to smb jobid */
1173
1174                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1175                         id = sysjob_to_jobid(msg->id);
1176
1177                         if (id == -1) {
1178                                 DEBUG(3, ("no such unix jobid %d\n",
1179                                           msg->id));
1180                                 continue;
1181                         }
1182                 }
1183
1184                 construct_info_data(&notifies[count],
1185                                     msg->type, msg->field, id);
1186
1187                 switch(msg->type) {
1188                 case PRINTER_NOTIFY_TYPE:
1189                         if (printer_notify_table[msg->field].fn) {
1190                                 printer_notify_table[msg->field].fn(msg,
1191                                                 &notifies[count], mem_ctx);
1192                         }
1193                         break;
1194
1195                 case JOB_NOTIFY_TYPE:
1196                         if (job_notify_table[msg->field].fn) {
1197                                 job_notify_table[msg->field].fn(msg,
1198                                                 &notifies[count], mem_ctx);
1199                         }
1200                         break;
1201
1202                 default:
1203                         DEBUG(5, ("Unknown notification type %d\n",
1204                                   msg->type));
1205                         continue;
1206                 }
1207
1208                 count++;
1209         }
1210
1211         *_notifies = notifies;
1212         *_count = count;
1213
1214         return 0;
1215 }
1216
1217 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1218                                 struct printer_handle *prn_hnd,
1219                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1220 {
1221         struct spoolss_Notify *notifies;
1222         int count = 0;
1223         union spoolss_ReplyPrinterInfo info;
1224         struct spoolss_NotifyInfo info0;
1225         uint32_t reply_result;
1226         NTSTATUS status;
1227         WERROR werr;
1228         int ret;
1229
1230         /* Is there notification on this handle? */
1231         if (prn_hnd->notify.cli_chan == NULL ||
1232             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1233             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1234             prn_hnd->notify.cli_chan->active_connections == 0) {
1235                 return 0;
1236         }
1237
1238         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1239                    prn_hnd->servername, prn_hnd->sharename));
1240
1241         /* For this printer? Print servers always receive notifications. */
1242         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1243             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1244                 return 0;
1245         }
1246
1247         DEBUG(10,("Our printer\n"));
1248
1249         /* build the array of change notifications */
1250         ret = build_notify2_messages(mem_ctx, prn_hnd,
1251                                      msg_group->msgs,
1252                                      msg_group->num_msgs,
1253                                      &notifies, &count);
1254         if (ret) {
1255                 return ret;
1256         }
1257
1258         info0.version   = 0x2;
1259         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1260         info0.count     = count;
1261         info0.notifies  = notifies;
1262
1263         info.info0 = &info0;
1264
1265         status = dcerpc_spoolss_RouterReplyPrinterEx(
1266                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1267                                 mem_ctx,
1268                                 &prn_hnd->notify.cli_hnd,
1269                                 prn_hnd->notify.change, /* color */
1270                                 prn_hnd->notify.flags,
1271                                 &reply_result,
1272                                 0, /* reply_type, must be 0 */
1273                                 info, &werr);
1274         if (!NT_STATUS_IS_OK(status)) {
1275                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1276                           "failed: %s\n",
1277                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1278                           nt_errstr(status)));
1279                 werr = ntstatus_to_werror(status);
1280         } else if (!W_ERROR_IS_OK(werr)) {
1281                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1282                           "failed: %s\n",
1283                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1284                           win_errstr(werr)));
1285         }
1286         switch (reply_result) {
1287         case 0:
1288                 break;
1289         case PRINTER_NOTIFY_INFO_DISCARDED:
1290         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1291         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1292                 break;
1293         default:
1294                 break;
1295         }
1296
1297         return 0;
1298 }
1299
1300 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1301 {
1302         struct printer_handle    *p;
1303         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1304         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1305         int ret;
1306
1307         if ( !msg_group ) {
1308                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1309                 return;
1310         }
1311
1312         if (!msg_group->msgs) {
1313                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1314                 return;
1315         }
1316
1317         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1318
1319         /* loop over all printers */
1320
1321         for (p = printers_list; p; p = p->next) {
1322                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1323                 if (ret) {
1324                         goto done;
1325                 }
1326         }
1327
1328 done:
1329         DEBUG(8,("send_notify2_changes: Exit...\n"));
1330         return;
1331 }
1332
1333 /***********************************************************************
1334  **********************************************************************/
1335
1336 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1337 {
1338
1339         uint32_t tv_sec, tv_usec;
1340         size_t offset = 0;
1341
1342         /* Unpack message */
1343
1344         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1345                              msg->printer);
1346
1347         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1348                                 &tv_sec, &tv_usec,
1349                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1350
1351         if (msg->len == 0)
1352                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1353                            &msg->notify.value[0], &msg->notify.value[1]);
1354         else
1355                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1356                            &msg->len, &msg->notify.data);
1357
1358         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1359                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1360
1361         tv->tv_sec = tv_sec;
1362         tv->tv_usec = tv_usec;
1363
1364         if (msg->len == 0)
1365                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1366                           msg->notify.value[1]));
1367         else
1368                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1369
1370         return true;
1371 }
1372
1373 /********************************************************************
1374  Receive a notify2 message list
1375  ********************************************************************/
1376
1377 static void receive_notify2_message_list(struct messaging_context *msg,
1378                                          void *private_data,
1379                                          uint32_t msg_type,
1380                                          struct server_id server_id,
1381                                          DATA_BLOB *data)
1382 {
1383         size_t                  msg_count, i;
1384         char                    *buf = (char *)data->data;
1385         char                    *msg_ptr;
1386         size_t                  msg_len;
1387         SPOOLSS_NOTIFY_MSG      notify;
1388         SPOOLSS_NOTIFY_MSG_CTR  messages;
1389         int                     num_groups;
1390
1391         if (data->length < 4) {
1392                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1393                 return;
1394         }
1395
1396         msg_count = IVAL(buf, 0);
1397         msg_ptr = buf + 4;
1398
1399         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1400
1401         if (msg_count == 0) {
1402                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1403                 return;
1404         }
1405
1406         /* initialize the container */
1407
1408         ZERO_STRUCT( messages );
1409         notify_msg_ctr_init( &messages );
1410
1411         /*
1412          * build message groups for each printer identified
1413          * in a change_notify msg.  Remember that a PCN message
1414          * includes the handle returned for the srv_spoolss_replyopenprinter()
1415          * call.  Therefore messages are grouped according to printer handle.
1416          */
1417
1418         for ( i=0; i<msg_count; i++ ) {
1419                 struct timeval msg_tv;
1420
1421                 if (msg_ptr + 4 - buf > data->length) {
1422                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1423                         return;
1424                 }
1425
1426                 msg_len = IVAL(msg_ptr,0);
1427                 msg_ptr += 4;
1428
1429                 if (msg_ptr + msg_len - buf > data->length) {
1430                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1431                         return;
1432                 }
1433
1434                 /* unpack messages */
1435
1436                 ZERO_STRUCT( notify );
1437                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1438                 msg_ptr += msg_len;
1439
1440                 /* add to correct list in container */
1441
1442                 notify_msg_ctr_addmsg( &messages, &notify );
1443
1444                 /* free memory that might have been allocated by notify2_unpack_msg() */
1445
1446                 if ( notify.len != 0 )
1447                         SAFE_FREE( notify.notify.data );
1448         }
1449
1450         /* process each group of messages */
1451
1452         num_groups = notify_msg_ctr_numgroups( &messages );
1453         for ( i=0; i<num_groups; i++ )
1454                 send_notify2_changes( &messages, i );
1455
1456
1457         /* cleanup */
1458
1459         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1460                 (uint32_t)msg_count ));
1461
1462         notify_msg_ctr_destroy( &messages );
1463
1464         return;
1465 }
1466
1467 /********************************************************************
1468  Send a message to ourself about new driver being installed
1469  so we can upgrade the information for each printer bound to this
1470  driver
1471  ********************************************************************/
1472
1473 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1474                                             struct messaging_context *msg_ctx)
1475 {
1476         int len = strlen(drivername);
1477
1478         if (!len)
1479                 return false;
1480
1481         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1482                 drivername));
1483
1484         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1485                            MSG_PRINTER_DRVUPGRADE,
1486                            (const uint8_t *)drivername, len+1);
1487
1488         return true;
1489 }
1490
1491 void srv_spoolss_cleanup(void)
1492 {
1493         struct printer_session_counter *session_counter;
1494
1495         for (session_counter = counter_list;
1496              session_counter != NULL;
1497              session_counter = counter_list) {
1498                 DLIST_REMOVE(counter_list, session_counter);
1499                 TALLOC_FREE(session_counter);
1500         }
1501 }
1502
1503 /**********************************************************************
1504  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1505  over all printers, upgrading ones as necessary
1506  This is now *ONLY* called inside the background lpq updater. JRA.
1507  **********************************************************************/
1508
1509 void do_drv_upgrade_printer(struct messaging_context *msg,
1510                             void *private_data,
1511                             uint32_t msg_type,
1512                             struct server_id server_id,
1513                             DATA_BLOB *data)
1514 {
1515         TALLOC_CTX *tmp_ctx;
1516         const struct auth_session_info *session_info = get_session_info_system();
1517         struct spoolss_PrinterInfo2 *pinfo2;
1518         WERROR result;
1519         const char *drivername;
1520         int snum;
1521         int n_services = lp_numservices();
1522         struct dcerpc_binding_handle *b = NULL;
1523
1524         tmp_ctx = talloc_new(NULL);
1525         if (!tmp_ctx) return;
1526
1527         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1528         if (!drivername) {
1529                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1530                 goto done;
1531         }
1532
1533         DEBUG(10, ("do_drv_upgrade_printer: "
1534                    "Got message for new driver [%s]\n", drivername));
1535
1536         /* Iterate the printer list */
1537
1538         for (snum = 0; snum < n_services; snum++) {
1539                 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1540                         continue;
1541                 }
1542
1543                 /* ignore [printers] share */
1544                 if (strequal(lp_const_servicename(snum), "printers")) {
1545                         continue;
1546                 }
1547
1548                 if (b == NULL) {
1549                         result = winreg_printer_binding_handle(tmp_ctx,
1550                                                                session_info,
1551                                                                msg,
1552                                                                &b);
1553                         if (!W_ERROR_IS_OK(result)) {
1554                                 break;
1555                         }
1556                 }
1557
1558                 result = winreg_get_printer(tmp_ctx, b,
1559                                             lp_const_servicename(snum),
1560                                             &pinfo2);
1561
1562                 if (!W_ERROR_IS_OK(result)) {
1563                         continue;
1564                 }
1565
1566                 if (!pinfo2->drivername) {
1567                         continue;
1568                 }
1569
1570                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1571                         continue;
1572                 }
1573
1574                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1575
1576                 /* all we care about currently is the change_id */
1577                 result = winreg_printer_update_changeid(tmp_ctx, b,
1578                                                         pinfo2->printername);
1579
1580                 if (!W_ERROR_IS_OK(result)) {
1581                         DEBUG(3, ("do_drv_upgrade_printer: "
1582                                   "Failed to update changeid [%s]\n",
1583                                   win_errstr(result)));
1584                 }
1585         }
1586
1587         /* all done */
1588 done:
1589         talloc_free(tmp_ctx);
1590 }
1591
1592 /********************************************************************
1593  Update the cache for all printq's with a registered client
1594  connection
1595  ********************************************************************/
1596
1597 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1598 {
1599         struct printer_handle *printer = printers_list;
1600         int snum;
1601
1602         /* loop through all printers and update the cache where
1603            a client is connected */
1604         while (printer) {
1605                 if ((printer->printer_type == SPLHND_PRINTER) &&
1606                     ((printer->notify.cli_chan != NULL) &&
1607                      (printer->notify.cli_chan->active_connections > 0))) {
1608                         snum = print_queue_snum(printer->sharename);
1609                         print_queue_status(msg_ctx, snum, NULL, NULL);
1610                 }
1611
1612                 printer = printer->next;
1613         }
1614
1615         return;
1616 }
1617
1618 /****************************************************************
1619  _spoolss_OpenPrinter
1620 ****************************************************************/
1621
1622 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1623                             struct spoolss_OpenPrinter *r)
1624 {
1625         struct spoolss_OpenPrinterEx e;
1626         struct spoolss_UserLevel1 level1;
1627         WERROR werr;
1628
1629         ZERO_STRUCT(level1);
1630
1631         e.in.printername        = r->in.printername;
1632         e.in.datatype           = r->in.datatype;
1633         e.in.devmode_ctr        = r->in.devmode_ctr;
1634         e.in.access_mask        = r->in.access_mask;
1635         e.in.userlevel_ctr.level                = 1;
1636         e.in.userlevel_ctr.user_info.level1     = &level1;
1637
1638         e.out.handle            = r->out.handle;
1639
1640         werr = _spoolss_OpenPrinterEx(p, &e);
1641
1642         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
1643                 /* OpenPrinterEx returns this for a bad
1644                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1645                  * instead.
1646                  */
1647                 werr = WERR_INVALID_PRINTER_NAME;
1648         }
1649
1650         return werr;
1651 }
1652
1653 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1654                               struct spoolss_DeviceMode *orig,
1655                               struct spoolss_DeviceMode **dest)
1656 {
1657         struct spoolss_DeviceMode *dm;
1658
1659         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1660         if (!dm) {
1661                 return WERR_NOT_ENOUGH_MEMORY;
1662         }
1663
1664         /* copy all values, then duplicate strings and structs */
1665         *dm = *orig;
1666
1667         dm->devicename = talloc_strdup(dm, orig->devicename);
1668         if (!dm->devicename) {
1669                 return WERR_NOT_ENOUGH_MEMORY;
1670         }
1671         dm->formname = talloc_strdup(dm, orig->formname);
1672         if (!dm->formname) {
1673                 return WERR_NOT_ENOUGH_MEMORY;
1674         }
1675         if (orig->driverextra_data.data) {
1676                 dm->driverextra_data.data =
1677                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1678                                         orig->driverextra_data.length);
1679                 if (!dm->driverextra_data.data) {
1680                         return WERR_NOT_ENOUGH_MEMORY;
1681                 }
1682         }
1683
1684         *dest = dm;
1685         return WERR_OK;
1686 }
1687
1688 /****************************************************************
1689  _spoolss_OpenPrinterEx
1690 ****************************************************************/
1691
1692 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1693                               struct spoolss_OpenPrinterEx *r)
1694 {
1695         int snum;
1696         char *raddr;
1697         char *rhost;
1698         struct printer_handle *Printer=NULL;
1699         WERROR result;
1700         int rc;
1701
1702         if (!r->in.printername) {
1703                 return WERR_INVALID_PARAMETER;
1704         }
1705
1706         if (!*r->in.printername) {
1707                 return WERR_INVALID_PARAMETER;
1708         }
1709
1710         if (r->in.userlevel_ctr.level > 3) {
1711                 return WERR_INVALID_PARAMETER;
1712         }
1713         if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1714             (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1715             (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1716                 return WERR_INVALID_PARAMETER;
1717         }
1718
1719         /*
1720          * The printcap printer share inventory is updated on client
1721          * enumeration. For clients that do not perform enumeration prior to
1722          * access, such as cupssmbadd, we reinitialise the printer share
1723          * inventory on open as well.
1724          */
1725         become_root();
1726         delete_and_reload_printers(server_event_context(), p->msg_ctx);
1727         unbecome_root();
1728
1729         /* some sanity check because you can open a printer or a print server */
1730         /* aka: \\server\printer or \\server */
1731
1732         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1733
1734         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1735         if (!W_ERROR_IS_OK(result)) {
1736                 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1737                         "for printer %s\n", r->in.printername));
1738                 ZERO_STRUCTP(r->out.handle);
1739                 return result;
1740         }
1741
1742         Printer = find_printer_index_by_hnd(p, r->out.handle);
1743         if ( !Printer ) {
1744                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1745                         "handle we created for printer %s\n", r->in.printername));
1746                 close_printer_handle(p, r->out.handle);
1747                 ZERO_STRUCTP(r->out.handle);
1748                 return WERR_INVALID_PARAMETER;
1749         }
1750
1751         /*
1752          * First case: the user is opening the print server:
1753          *
1754          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1755          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1756          *
1757          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1758          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1759          * or if the user is listed in the smb.conf printer admin parameter.
1760          *
1761          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1762          * client view printer folder, but does not show the MSAPW.
1763          *
1764          * Note: this test needs code to check access rights here too. Jeremy
1765          * could you look at this?
1766          *
1767          * Second case: the user is opening a printer:
1768          * NT doesn't let us connect to a printer if the connecting user
1769          * doesn't have print permission.
1770          *
1771          * Third case: user is opening a Port Monitor
1772          * access checks same as opening a handle to the print server.
1773          */
1774
1775         switch (Printer->printer_type )
1776         {
1777         case SPLHND_SERVER:
1778         case SPLHND_PORTMON_TCP:
1779         case SPLHND_PORTMON_LOCAL:
1780                 /* Printserver handles use global struct... */
1781
1782                 snum = -1;
1783
1784                 if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
1785                         r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
1786                         r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
1787                 }
1788
1789                 /* Map standard access rights to object specific access rights */
1790
1791                 se_map_standard(&r->in.access_mask,
1792                                 &printserver_std_mapping);
1793
1794                 /* Deny any object specific bits that don't apply to print
1795                    servers (i.e printer and job specific bits) */
1796
1797                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1798
1799                 if (r->in.access_mask &
1800                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1801                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1802                         close_printer_handle(p, r->out.handle);
1803                         ZERO_STRUCTP(r->out.handle);
1804                         return WERR_ACCESS_DENIED;
1805                 }
1806
1807                 /* Allow admin access */
1808
1809                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1810                 {
1811                         if (!lp_show_add_printer_wizard()) {
1812                                 close_printer_handle(p, r->out.handle);
1813                                 ZERO_STRUCTP(r->out.handle);
1814                                 return WERR_ACCESS_DENIED;
1815                         }
1816
1817                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1818                            and not a printer admin, then fail */
1819
1820                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1821                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1822                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1823                                                 p->session_info->security_token)) {
1824                                 close_printer_handle(p, r->out.handle);
1825                                 ZERO_STRUCTP(r->out.handle);
1826                                 DEBUG(3,("access DENIED as user is not root, "
1827                                         "has no printoperator privilege and is "
1828                                         "not a member of the printoperator builtin group\n"));
1829                                 return WERR_ACCESS_DENIED;
1830                         }
1831
1832                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1833                 }
1834                 else
1835                 {
1836                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1837                 }
1838
1839                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1840                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1841
1842                 /* We fall through to return WERR_OK */
1843                 break;
1844
1845         case SPLHND_PRINTER:
1846                 /* NT doesn't let us connect to a printer if the connecting user
1847                    doesn't have print permission.  */
1848
1849                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1850                         close_printer_handle(p, r->out.handle);
1851                         ZERO_STRUCTP(r->out.handle);
1852                         return WERR_INVALID_HANDLE;
1853                 }
1854
1855                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1856                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1857                 }
1858
1859                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1860
1861                 /* map an empty access mask to the minimum access mask */
1862                 if (r->in.access_mask == 0x0)
1863                         r->in.access_mask = PRINTER_ACCESS_USE;
1864
1865                 /*
1866                  * If we are not serving the printer driver for this printer,
1867                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1868                  * will keep NT clients happy  --jerry
1869                  */
1870
1871                 if (lp_use_client_driver(snum)
1872                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1873                 {
1874                         r->in.access_mask = PRINTER_ACCESS_USE;
1875                 }
1876
1877                 /* check smb.conf parameters and the the sec_desc */
1878                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1879                                                          p->mem_ctx);
1880                 if (raddr == NULL) {
1881                         return WERR_NOT_ENOUGH_MEMORY;
1882                 }
1883
1884                 rc = get_remote_hostname(p->remote_address,
1885                                          &rhost,
1886                                          p->mem_ctx);
1887                 if (rc < 0) {
1888                         return WERR_NOT_ENOUGH_MEMORY;
1889                 }
1890                 if (strequal(rhost, "UNKNOWN")) {
1891                         rhost = raddr;
1892                 }
1893
1894                 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1895                                   rhost, raddr)) {
1896                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1897                         ZERO_STRUCTP(r->out.handle);
1898                         return WERR_ACCESS_DENIED;
1899                 }
1900
1901                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1902                                    p->session_info->security_token, snum) ||
1903                     !W_ERROR_IS_OK(print_access_check(p->session_info,
1904                                                       p->msg_ctx,
1905                                                       snum,
1906                                                       r->in.access_mask))) {
1907                         DEBUG(3, ("access DENIED for printer open\n"));
1908                         close_printer_handle(p, r->out.handle);
1909                         ZERO_STRUCTP(r->out.handle);
1910                         return WERR_ACCESS_DENIED;
1911                 }
1912
1913                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1914                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1915                         close_printer_handle(p, r->out.handle);
1916                         ZERO_STRUCTP(r->out.handle);
1917                         return WERR_ACCESS_DENIED;
1918                 }
1919
1920                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1921                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1922                 else
1923                         r->in.access_mask = PRINTER_ACCESS_USE;
1924
1925                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1926                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1927
1928                 winreg_create_printer_internal(p->mem_ctx,
1929                                       get_session_info_system(),
1930                                       p->msg_ctx,
1931                                       lp_const_servicename(snum));
1932
1933                 break;
1934
1935         default:
1936                 /* sanity check to prevent programmer error */
1937                 ZERO_STRUCTP(r->out.handle);
1938                 return WERR_INVALID_HANDLE;
1939         }
1940
1941         Printer->access_granted = r->in.access_mask;
1942
1943         /*
1944          * If the client sent a devmode in the OpenPrinter() call, then
1945          * save it here in case we get a job submission on this handle
1946          */
1947
1948          if ((Printer->printer_type != SPLHND_SERVER)
1949           && (r->in.devmode_ctr.devmode != NULL)) {
1950                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1951                                 &Printer->devmode);
1952          }
1953
1954         return WERR_OK;
1955 }
1956
1957 /****************************************************************
1958  _spoolss_ClosePrinter
1959 ****************************************************************/
1960
1961 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1962                              struct spoolss_ClosePrinter *r)
1963 {
1964         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1965
1966         if (Printer && Printer->document_started) {
1967                 struct spoolss_EndDocPrinter e;
1968
1969                 e.in.handle = r->in.handle;
1970
1971                 _spoolss_EndDocPrinter(p, &e);
1972         }
1973
1974         if (!close_printer_handle(p, r->in.handle))
1975                 return WERR_INVALID_HANDLE;
1976
1977         /* clear the returned printer handle.  Observed behavior
1978            from Win2k server.  Don't think this really matters.
1979            Previous code just copied the value of the closed
1980            handle.    --jerry */
1981
1982         ZERO_STRUCTP(r->out.handle);
1983
1984         return WERR_OK;
1985 }
1986
1987 /****************************************************************
1988  _spoolss_DeletePrinter
1989 ****************************************************************/
1990
1991 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1992                               struct spoolss_DeletePrinter *r)
1993 {
1994         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1995         WERROR result;
1996         int snum;
1997
1998         if (Printer && Printer->document_started) {
1999                 struct spoolss_EndDocPrinter e;
2000
2001                 e.in.handle = r->in.handle;
2002
2003                 _spoolss_EndDocPrinter(p, &e);
2004         }
2005
2006         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2007                 winreg_delete_printer_key_internal(p->mem_ctx,
2008                                           get_session_info_system(),
2009                                           p->msg_ctx,
2010                                           lp_const_servicename(snum),
2011                                           "");
2012         }
2013
2014         result = delete_printer_handle(p, r->in.handle);
2015
2016         return result;
2017 }
2018
2019 /*******************************************************************
2020  * static function to lookup the version id corresponding to an
2021  * long architecture string
2022  ******************************************************************/
2023
2024 static const struct print_architecture_table_node archi_table[]= {
2025
2026         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2027         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2028         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2029         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2030         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2031         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2032         {"Windows x64",          SPL_ARCH_X64,          3 },
2033         {NULL,                   "",            -1 }
2034 };
2035
2036 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2037                                    SPOOLSS_DRIVER_VERSION_NT35,
2038                                    SPOOLSS_DRIVER_VERSION_NT4,
2039                                    SPOOLSS_DRIVER_VERSION_200X,
2040                                    -1};
2041
2042 static int get_version_id(const char *arch)
2043 {
2044         int i;
2045
2046         for (i=0; archi_table[i].long_archi != NULL; i++)
2047         {
2048                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2049                         return (archi_table[i].version);
2050         }
2051
2052         return -1;
2053 }
2054
2055 /****************************************************************
2056  _spoolss_DeletePrinterDriver
2057 ****************************************************************/
2058
2059 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2060                                     struct spoolss_DeletePrinterDriver *r)
2061 {
2062
2063         struct spoolss_DriverInfo8 *info = NULL;
2064         int                             version;
2065         WERROR                          status;
2066         struct dcerpc_binding_handle *b;
2067         TALLOC_CTX *tmp_ctx = NULL;
2068         int i;
2069         bool found;
2070
2071         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2072            and not a printer admin, then fail */
2073
2074         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2075             !security_token_has_privilege(p->session_info->security_token,
2076                                           SEC_PRIV_PRINT_OPERATOR)) {
2077                 return WERR_ACCESS_DENIED;
2078         }
2079
2080         /* check that we have a valid driver name first */
2081
2082         if ((version = get_version_id(r->in.architecture)) == -1) {
2083                 return WERR_INVALID_ENVIRONMENT;
2084         }
2085
2086         tmp_ctx = talloc_new(p->mem_ctx);
2087         if (!tmp_ctx) {
2088                 return WERR_NOT_ENOUGH_MEMORY;
2089         }
2090
2091         status = winreg_printer_binding_handle(tmp_ctx,
2092                                                get_session_info_system(),
2093                                                p->msg_ctx,
2094                                                &b);
2095         if (!W_ERROR_IS_OK(status)) {
2096                 goto done;
2097         }
2098
2099         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2100                 status = winreg_get_driver(tmp_ctx, b,
2101                                            r->in.architecture, r->in.driver,
2102                                            drv_cversion[i], &info);
2103                 if (!W_ERROR_IS_OK(status)) {
2104                         DEBUG(5, ("skipping del of driver with version %d\n",
2105                                   drv_cversion[i]));
2106                         continue;
2107                 }
2108                 found = true;
2109
2110                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2111                         status = WERR_PRINTER_DRIVER_IN_USE;
2112                         goto done;
2113                 }
2114
2115                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2116                 if (!W_ERROR_IS_OK(status)) {
2117                         DEBUG(0, ("failed del of driver with version %d\n",
2118                                   drv_cversion[i]));
2119                         goto done;
2120                 }
2121         }
2122         if (found == false) {
2123                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2124                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2125         } else {
2126                 status = WERR_OK;
2127         }
2128
2129 done:
2130         talloc_free(tmp_ctx);
2131
2132         return status;
2133 }
2134
2135 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2136                                   struct pipes_struct *p,
2137                                   struct spoolss_DeletePrinterDriverEx *r,
2138                                   struct dcerpc_binding_handle *b,
2139                                   struct spoolss_DriverInfo8 *info)
2140 {
2141         WERROR status;
2142         bool delete_files;
2143
2144         if (printer_driver_in_use(mem_ctx, b, info)) {
2145                 status = WERR_PRINTER_DRIVER_IN_USE;
2146                 goto done;
2147         }
2148
2149         /*
2150          * we have a couple of cases to consider.
2151          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2152          *     then the delete should fail if **any** files overlap with
2153          *     other drivers
2154          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2155          *     non-overlapping files
2156          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2157          *     are set, then do not delete any files
2158          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2159          */
2160
2161         delete_files = r->in.delete_flags
2162                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2163
2164
2165         if (delete_files) {
2166                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2167                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2168                         status = WERR_PRINTER_DRIVER_IN_USE;
2169                         goto done;
2170                 }
2171                 /*
2172                  * printer_driver_files_in_use() has trimmed overlapping files
2173                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2174                  */
2175         }
2176
2177
2178         status = winreg_del_driver(mem_ctx, b, info, info->version);
2179         if (!W_ERROR_IS_OK(status)) {
2180                 goto done;
2181         }
2182
2183         /*
2184          * now delete any associated files if delete_files is
2185          * true. Even if this part failes, we return succes
2186          * because the driver doesn not exist any more
2187          */
2188         if (delete_files) {
2189                 delete_driver_files(p->session_info, info);
2190         }
2191
2192 done:
2193         return status;
2194 }
2195
2196 /****************************************************************
2197  _spoolss_DeletePrinterDriverEx
2198 ****************************************************************/
2199
2200 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2201                                       struct spoolss_DeletePrinterDriverEx *r)
2202 {
2203         struct spoolss_DriverInfo8 *info = NULL;
2204         WERROR                          status;
2205         struct dcerpc_binding_handle *b;
2206         TALLOC_CTX *tmp_ctx = NULL;
2207         int i;
2208         bool found;
2209
2210         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2211            and not a printer admin, then fail */
2212
2213         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2214             !security_token_has_privilege(p->session_info->security_token,
2215                                           SEC_PRIV_PRINT_OPERATOR)) {
2216                 return WERR_ACCESS_DENIED;
2217         }
2218
2219         /* check that we have a valid driver name first */
2220         if (get_version_id(r->in.architecture) == -1) {
2221                 /* this is what NT returns */
2222                 return WERR_INVALID_ENVIRONMENT;
2223         }
2224
2225         tmp_ctx = talloc_new(p->mem_ctx);
2226         if (!tmp_ctx) {
2227                 return WERR_NOT_ENOUGH_MEMORY;
2228         }
2229
2230         status = winreg_printer_binding_handle(tmp_ctx,
2231                                                get_session_info_system(),
2232                                                p->msg_ctx,
2233                                                &b);
2234         if (!W_ERROR_IS_OK(status)) {
2235                 goto done;
2236         }
2237
2238         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2239                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2240                  && (drv_cversion[i] != r->in.version)) {
2241                         continue;
2242                 }
2243
2244                 /* check if a driver with this version exists before delete */
2245                 status = winreg_get_driver(tmp_ctx, b,
2246                                            r->in.architecture, r->in.driver,
2247                                            drv_cversion[i], &info);
2248                 if (!W_ERROR_IS_OK(status)) {
2249                         DEBUG(5, ("skipping del of driver with version %d\n",
2250                                   drv_cversion[i]));
2251                         continue;
2252                 }
2253                 found = true;
2254
2255                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2256                 if (!W_ERROR_IS_OK(status)) {
2257                         DEBUG(0, ("failed to delete driver with version %d\n",
2258                                   drv_cversion[i]));
2259                         goto done;
2260                 }
2261         }
2262         if (found == false) {
2263                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2264                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2265         } else {
2266                 status = WERR_OK;
2267         }
2268
2269 done:
2270         talloc_free(tmp_ctx);
2271         return status;
2272 }
2273
2274
2275 /********************************************************************
2276  GetPrinterData on a printer server Handle.
2277 ********************************************************************/
2278
2279 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2280                                             const char *value,
2281                                             enum winreg_Type *type,
2282                                             union spoolss_PrinterData *data)
2283 {
2284         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2285
2286         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2287                 *type = REG_DWORD;
2288                 SIVAL(&data->value, 0, 0x00);
2289                 return WERR_OK;
2290         }
2291
2292         if (!strcasecmp_m(value, "BeepEnabled")) {
2293                 *type = REG_DWORD;
2294                 SIVAL(&data->value, 0, 0x00);
2295                 return WERR_OK;
2296         }
2297
2298         if (!strcasecmp_m(value, "EventLog")) {
2299                 *type = REG_DWORD;
2300                 /* formally was 0x1b */
2301                 SIVAL(&data->value, 0, 0x00);
2302                 return WERR_OK;
2303         }
2304
2305         if (!strcasecmp_m(value, "NetPopup")) {
2306                 *type = REG_DWORD;
2307                 SIVAL(&data->value, 0, 0x00);
2308                 return WERR_OK;
2309         }
2310
2311         if (!strcasecmp_m(value, "MajorVersion")) {
2312                 *type = REG_DWORD;
2313
2314                 /* Windows NT 4.0 seems to not allow uploading of drivers
2315                    to a server that reports 0x3 as the MajorVersion.
2316                    need to investigate more how Win2k gets around this .
2317                    -- jerry */
2318
2319                 if (RA_WINNT == get_remote_arch()) {
2320                         SIVAL(&data->value, 0, 0x02);
2321                 } else {
2322                         SIVAL(&data->value, 0, 0x03);
2323                 }
2324
2325                 return WERR_OK;
2326         }
2327
2328         if (!strcasecmp_m(value, "MinorVersion")) {
2329                 *type = REG_DWORD;
2330                 SIVAL(&data->value, 0, 0x00);
2331                 return WERR_OK;
2332         }
2333
2334         /* REG_BINARY
2335          *  uint32_t size        = 0x114
2336          *  uint32_t major       = 5
2337          *  uint32_t minor       = [0|1]
2338          *  uint32_t build       = [2195|2600]
2339          *  extra unicode string = e.g. "Service Pack 3"
2340          */
2341         if (!strcasecmp_m(value, "OSVersion")) {
2342                 DATA_BLOB blob;
2343                 enum ndr_err_code ndr_err;
2344                 struct spoolss_OSVersion os;
2345
2346                 os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
2347                                                       "spoolss", "os_major", 5);
2348                                                       /* Windows 2000 == 5.0 */
2349                 os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
2350                                                       "spoolss", "os_minor", 0);
2351                 os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
2352                                                       "spoolss", "os_build", 2195);
2353                 os.extra_string         = "";   /* leave extra string empty */
2354
2355                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2356                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2357                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2358                         return WERR_GEN_FAILURE;
2359                 }
2360
2361                 if (DEBUGLEVEL >= 10) {
2362                         NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2363                 }
2364
2365                 *type = REG_BINARY;
2366                 data->binary = blob;
2367
2368                 return WERR_OK;
2369         }
2370
2371
2372         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2373                 *type = REG_SZ;
2374
2375                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2376                 W_ERROR_HAVE_NO_MEMORY(data->string);
2377
2378                 return WERR_OK;
2379         }
2380
2381         if (!strcasecmp_m(value, "Architecture")) {
2382                 *type = REG_SZ;
2383                 data->string = talloc_strdup(mem_ctx,
2384                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2385                 W_ERROR_HAVE_NO_MEMORY(data->string);
2386
2387                 return WERR_OK;
2388         }
2389
2390         if (!strcasecmp_m(value, "DsPresent")) {
2391                 *type = REG_DWORD;
2392
2393                 /* only show the publish check box if we are a
2394                    member of a AD domain */
2395
2396                 if (lp_security() == SEC_ADS) {
2397                         SIVAL(&data->value, 0, 0x01);
2398                 } else {
2399                         SIVAL(&data->value, 0, 0x00);
2400                 }
2401                 return WERR_OK;
2402         }
2403
2404         if (!strcasecmp_m(value, "DNSMachineName")) {
2405                 const char *hostname = get_mydnsfullname();
2406
2407                 if (!hostname) {
2408                         return WERR_FILE_NOT_FOUND;
2409                 }
2410
2411                 *type = REG_SZ;
2412                 data->string = talloc_strdup(mem_ctx, hostname);
2413                 W_ERROR_HAVE_NO_MEMORY(data->string);
2414
2415                 return WERR_OK;
2416         }
2417
2418         *type = REG_NONE;
2419
2420         return WERR_INVALID_PARAMETER;
2421 }
2422
2423 /****************************************************************
2424  _spoolss_GetPrinterData
2425 ****************************************************************/
2426
2427 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2428                                struct spoolss_GetPrinterData *r)
2429 {
2430         struct spoolss_GetPrinterDataEx r2;
2431
2432         r2.in.handle            = r->in.handle;
2433         r2.in.key_name          = "PrinterDriverData";
2434         r2.in.value_name        = r->in.value_name;
2435         r2.in.offered           = r->in.offered;
2436         r2.out.type             = r->out.type;
2437         r2.out.data             = r->out.data;
2438         r2.out.needed           = r->out.needed;
2439
2440         return _spoolss_GetPrinterDataEx(p, &r2);
2441 }
2442
2443 /*********************************************************
2444  Connect to the client machine.
2445 **********************************************************/
2446
2447 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2448                                       struct sockaddr_storage *client_ss, const char *remote_machine)
2449 {
2450         NTSTATUS ret;
2451         struct sockaddr_storage rm_addr;
2452         char addr[INET6_ADDRSTRLEN];
2453
2454         if ( is_zero_addr(client_ss) ) {
2455                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2456                         remote_machine));
2457                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2458                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2459                         return false;
2460                 }
2461                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2462         } else {
2463                 rm_addr = *client_ss;
2464                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2465                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2466                         addr));
2467         }
2468
2469         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2470                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2471                         addr));
2472                 return false;
2473         }
2474
2475         /* setup the connection */
2476         ret = cli_full_connection( pp_cli, lp_netbios_name(), remote_machine,
2477                 &rm_addr, 0, "IPC$", "IPC",
2478                 "", /* username */
2479                 "", /* domain */
2480                 "", /* password */
2481                 0, lp_client_signing());
2482
2483         if ( !NT_STATUS_IS_OK( ret ) ) {
2484                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2485                         remote_machine ));
2486                 return false;
2487         }
2488
2489         if ( smbXcli_conn_protocol((*pp_cli)->conn) != PROTOCOL_NT1 ) {
2490                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2491                 cli_shutdown(*pp_cli);
2492                 return false;
2493         }
2494
2495         /*
2496          * Ok - we have an anonymous connection to the IPC$ share.
2497          * Now start the NT Domain stuff :-).
2498          */
2499
2500         ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2501         if (!NT_STATUS_IS_OK(ret)) {
2502                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2503                         remote_machine, nt_errstr(ret)));
2504                 cli_shutdown(*pp_cli);
2505                 return false;
2506         }
2507
2508         return true;
2509 }
2510
2511 /***************************************************************************
2512  Connect to the client.
2513 ****************************************************************************/
2514
2515 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2516                                         uint32_t localprinter,
2517                                         enum winreg_Type type,
2518                                         struct policy_handle *handle,
2519                                         struct notify_back_channel **_chan,
2520                                         struct sockaddr_storage *client_ss,
2521                                         struct messaging_context *msg_ctx)
2522 {
2523         WERROR result;
2524         NTSTATUS status;
2525         struct notify_back_channel *chan;
2526
2527         for (chan = back_channels; chan; chan = chan->next) {
2528                 if (memcmp(&chan->client_address, client_ss,
2529                            sizeof(struct sockaddr_storage)) == 0) {
2530                         break;
2531                 }
2532         }
2533
2534         /*
2535          * If it's the first connection, contact the client
2536          * and connect to the IPC$ share anonymously
2537          */
2538         if (!chan) {
2539                 fstring unix_printer;
2540
2541                 /* the +2 is to strip the leading 2 backslashs */
2542                 fstrcpy(unix_printer, printer + 2);
2543
2544                 chan = talloc_zero(NULL, struct notify_back_channel);
2545                 if (!chan) {
2546                         return false;
2547                 }
2548                 chan->client_address = *client_ss;
2549
2550                 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2551                         TALLOC_FREE(chan);
2552                         return false;
2553                 }
2554
2555                 DLIST_ADD(back_channels, chan);
2556
2557                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2558                                    receive_notify2_message_list);
2559         }
2560
2561         if (chan->cli_pipe == NULL ||
2562             chan->cli_pipe->binding_handle == NULL) {
2563                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2564                         "NULL %s for printer %s\n",
2565                         chan->cli_pipe == NULL ?
2566                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2567                         printer));
2568                 return false;
2569         }
2570
2571         /*
2572          * Tell the specific printing tdb we want messages for this printer
2573          * by registering our PID.
2574          */
2575
2576         if (!print_notify_register_pid(snum)) {
2577                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2578                           printer));
2579         }
2580
2581         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2582                                                  talloc_tos(),
2583                                                  printer,
2584                                                  localprinter,
2585                                                  type,
2586                                                  0,
2587                                                  NULL,
2588                                                  handle,
2589                                                  &result);
2590         if (!NT_STATUS_IS_OK(status)) {
2591                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2592                 result = ntstatus_to_werror(status);
2593         } else if (!W_ERROR_IS_OK(result)) {
2594                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2595         }
2596
2597         chan->active_connections++;
2598         *_chan = chan;
2599
2600         return (W_ERROR_IS_OK(result));
2601 }
2602
2603 /****************************************************************
2604  ****************************************************************/
2605
2606 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2607                                                              const struct spoolss_NotifyOption *r)
2608 {
2609         struct spoolss_NotifyOption *option;
2610         uint32_t i,k;
2611
2612         if (!r) {
2613                 return NULL;
2614         }
2615
2616         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2617         if (!option) {
2618                 return NULL;
2619         }
2620
2621         *option = *r;
2622
2623         if (!option->count) {
2624                 return option;
2625         }
2626
2627         option->types = talloc_zero_array(option,
2628                 struct spoolss_NotifyOptionType, option->count);
2629         if (!option->types) {
2630                 talloc_free(option);
2631                 return NULL;
2632         }
2633
2634         for (i=0; i < option->count; i++) {
2635                 option->types[i] = r->types[i];
2636
2637                 if (option->types[i].count) {
2638                         option->types[i].fields = talloc_zero_array(option,
2639                                 union spoolss_Field, option->types[i].count);
2640                         if (!option->types[i].fields) {
2641                                 talloc_free(option);
2642                                 return NULL;
2643                         }
2644                         for (k=0; k<option->types[i].count; k++) {
2645                                 option->types[i].fields[k] =
2646                                         r->types[i].fields[k];
2647                         }
2648                 }
2649         }
2650
2651         return option;
2652 }
2653
2654 /****************************************************************
2655  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2656  *
2657  * before replying OK: status=0 a rpc call is made to the workstation
2658  * asking ReplyOpenPrinter
2659  *
2660  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2661  * called from api_spoolss_rffpcnex
2662 ****************************************************************/
2663
2664 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2665                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2666 {
2667         int snum = -1;
2668         struct spoolss_NotifyOption *option = r->in.notify_options;
2669         struct sockaddr_storage client_ss;
2670         ssize_t client_len;
2671
2672         /* store the notify value in the printer struct */
2673
2674         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2675
2676         if (!Printer) {
2677                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2678                         "Invalid handle (%s:%u:%u).\n",
2679                         OUR_HANDLE(r->in.handle)));
2680                 return WERR_INVALID_HANDLE;
2681         }
2682
2683         Printer->notify.flags           = r->in.flags;
2684         Printer->notify.options         = r->in.options;
2685         Printer->notify.printerlocal    = r->in.printer_local;
2686         Printer->notify.msg_ctx         = p->msg_ctx;
2687
2688         TALLOC_FREE(Printer->notify.option);
2689         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2690
2691         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2692
2693         /* Connect to the client machine and send a ReplyOpenPrinter */
2694
2695         if ( Printer->printer_type == SPLHND_SERVER)
2696                 snum = -1;
2697         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2698                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2699                 return WERR_INVALID_HANDLE;
2700
2701         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2702                   "remote_address is %s\n",
2703                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2704
2705         if (!lp_print_notify_backchannel(snum)) {
2706                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2707                         "backchannel disabled\n"));
2708                 return WERR_RPC_S_SERVER_UNAVAILABLE;
2709         }
2710
2711         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2712                                                   (struct sockaddr *) &client_ss,
2713                                                   sizeof(struct sockaddr_storage));
2714         if (client_len < 0) {
2715                 return WERR_NOT_ENOUGH_MEMORY;
2716         }
2717
2718         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2719                                         Printer->notify.printerlocal, REG_SZ,
2720                                         &Printer->notify.cli_hnd,
2721                                         &Printer->notify.cli_chan,
2722                                         &client_ss, p->msg_ctx)) {
2723                 return WERR_RPC_S_SERVER_UNAVAILABLE;
2724         }
2725
2726         return WERR_OK;
2727 }
2728
2729 /*******************************************************************
2730  * fill a notify_info_data with the servername
2731  ********************************************************************/
2732
2733 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2734                                        int snum,
2735                                        struct spoolss_Notify *data,
2736                                        print_queue_struct *queue,
2737                                        struct spoolss_PrinterInfo2 *pinfo2,
2738                                        TALLOC_CTX *mem_ctx)
2739 {
2740         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2741 }
2742
2743 /*******************************************************************
2744  * fill a notify_info_data with the printername (not including the servername).
2745  ********************************************************************/
2746
2747 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2748                                         int snum,
2749                                         struct spoolss_Notify *data,
2750                                         print_queue_struct *queue,
2751                                         struct spoolss_PrinterInfo2 *pinfo2,
2752                                         TALLOC_CTX *mem_ctx)
2753 {
2754         /* the notify name should not contain the \\server\ part */
2755         const char *p = strrchr(pinfo2->printername, '\\');
2756
2757         if (!p) {
2758                 p = pinfo2->printername;
2759         } else {
2760                 p++;
2761         }
2762
2763         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2764 }
2765
2766 /*******************************************************************
2767  * fill a notify_info_data with the servicename
2768  ********************************************************************/
2769
2770 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2771                                       int snum,
2772                                       struct spoolss_Notify *data,
2773                                       print_queue_struct *queue,
2774                                       struct spoolss_PrinterInfo2 *pinfo2,
2775                                       TALLOC_CTX *mem_ctx)
2776 {
2777         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2778 }
2779
2780 /*******************************************************************
2781  * fill a notify_info_data with the port name
2782  ********************************************************************/
2783
2784 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2785                                      int snum,
2786                                      struct spoolss_Notify *data,
2787                                      print_queue_struct *queue,
2788                                      struct spoolss_PrinterInfo2 *pinfo2,
2789                                      TALLOC_CTX *mem_ctx)
2790 {
2791         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2792 }
2793
2794 /*******************************************************************
2795  * fill a notify_info_data with the printername
2796  * but it doesn't exist, have to see what to do
2797  ********************************************************************/
2798
2799 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2800                                        int snum,
2801                                        struct spoolss_Notify *data,
2802                                        print_queue_struct *queue,
2803                                        struct spoolss_PrinterInfo2 *pinfo2,
2804                                        TALLOC_CTX *mem_ctx)
2805 {
2806         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2807 }
2808
2809 /*******************************************************************
2810  * fill a notify_info_data with the comment
2811  ********************************************************************/
2812
2813 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2814                                    int snum,
2815                                    struct spoolss_Notify *data,
2816                                    print_queue_struct *queue,
2817                                    struct spoolss_PrinterInfo2 *pinfo2,
2818                                    TALLOC_CTX *mem_ctx)
2819 {
2820         const char *p;
2821
2822         if (*pinfo2->comment == '\0') {
2823                 p = lp_comment(talloc_tos(), snum);
2824         } else {
2825                 p = pinfo2->comment;
2826         }
2827
2828         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2829 }
2830
2831 /*******************************************************************
2832  * fill a notify_info_data with the comment
2833  * location = "Room 1, floor 2, building 3"
2834  ********************************************************************/
2835
2836 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2837                                     int snum,
2838                                     struct spoolss_Notify *data,
2839                                     print_queue_struct *queue,
2840                                     struct spoolss_PrinterInfo2 *pinfo2,
2841                                     TALLOC_CTX *mem_ctx)
2842 {
2843         const char *loc = pinfo2->location;
2844         NTSTATUS status;
2845
2846         status = printer_list_get_printer(mem_ctx,
2847                                           pinfo2->sharename,
2848                                           NULL,
2849                                           &loc,
2850                                           NULL);
2851         if (NT_STATUS_IS_OK(status)) {
2852                 if (loc == NULL) {
2853                         loc = pinfo2->location;
2854                 }
2855         }
2856
2857         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2858 }
2859
2860 /*******************************************************************
2861  * fill a notify_info_data with the device mode
2862  * jfm:xxxx don't to it for know but that's a real problem !!!
2863  ********************************************************************/
2864
2865 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2866                                    int snum,
2867                                    struct spoolss_Notify *data,
2868                                    print_queue_struct *queue,
2869                                    struct spoolss_PrinterInfo2 *pinfo2,
2870                                    TALLOC_CTX *mem_ctx)
2871 {
2872         /* for a dummy implementation we have to zero the fields */
2873         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2874 }
2875
2876 /*******************************************************************
2877  * fill a notify_info_data with the separator file name
2878  ********************************************************************/
2879
2880 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2881                                    int snum,
2882                                    struct spoolss_Notify *data,
2883                                    print_queue_struct *queue,
2884                                    struct spoolss_PrinterInfo2 *pinfo2,
2885                                    TALLOC_CTX *mem_ctx)
2886 {
2887         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2888 }
2889
2890 /*******************************************************************
2891  * fill a notify_info_data with the print processor
2892  * jfm:xxxx return always winprint to indicate we don't do anything to it
2893  ********************************************************************/
2894
2895 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2896                                            int snum,
2897                                            struct spoolss_Notify *data,
2898                                            print_queue_struct *queue,
2899                                            struct spoolss_PrinterInfo2 *pinfo2,
2900                                            TALLOC_CTX *mem_ctx)
2901 {
2902         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2903 }
2904
2905 /*******************************************************************
2906  * fill a notify_info_data with the print processor options
2907  * jfm:xxxx send an empty string
2908  ********************************************************************/
2909
2910 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2911                                       int snum,
2912                                       struct spoolss_Notify *data,
2913                                       print_queue_struct *queue,
2914                                       struct spoolss_PrinterInfo2 *pinfo2,
2915                                       TALLOC_CTX *mem_ctx)
2916 {
2917         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2918 }
2919
2920 /*******************************************************************
2921  * fill a notify_info_data with the data type
2922  * jfm:xxxx always send RAW as data type
2923  ********************************************************************/
2924
2925 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2926                                     int snum,
2927                                     struct spoolss_Notify *data,
2928                                     print_queue_struct *queue,
2929                                     struct spoolss_PrinterInfo2 *pinfo2,
2930                                     TALLOC_CTX *mem_ctx)
2931 {
2932         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2933 }
2934
2935 /*******************************************************************
2936  * fill a notify_info_data with the security descriptor
2937  * jfm:xxxx send an null pointer to say no security desc
2938  * have to implement security before !
2939  ********************************************************************/
2940
2941 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2942                                          int snum,
2943                                          struct spoolss_Notify *data,
2944                                          print_queue_struct *queue,
2945                                          struct spoolss_PrinterInfo2 *pinfo2,
2946                                          TALLOC_CTX *mem_ctx)
2947 {
2948         if (pinfo2->secdesc == NULL) {
2949                 data->data.sd.sd = NULL;
2950         } else {
2951                 data->data.sd.sd = security_descriptor_copy(mem_ctx,
2952                                                             pinfo2->secdesc);
2953         }
2954         data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2955                                                              0);
2956 }
2957
2958 /*******************************************************************
2959  * fill a notify_info_data with the attributes
2960  * jfm:xxxx a samba printer is always shared
2961  ********************************************************************/
2962
2963 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2964                                       int snum,
2965                                       struct spoolss_Notify *data,
2966                                       print_queue_struct *queue,
2967                                       struct spoolss_PrinterInfo2 *pinfo2,
2968                                       TALLOC_CTX *mem_ctx)
2969 {
2970         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2971 }
2972
2973 /*******************************************************************
2974  * fill a notify_info_data with the priority
2975  ********************************************************************/
2976
2977 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2978                                     int snum,
2979                                     struct spoolss_Notify *data,
2980                                     print_queue_struct *queue,
2981                                     struct spoolss_PrinterInfo2 *pinfo2,
2982                                     TALLOC_CTX *mem_ctx)
2983 {
2984         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2985 }
2986
2987 /*******************************************************************
2988  * fill a notify_info_data with the default priority
2989  ********************************************************************/
2990
2991 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2992                                             int snum,
2993                                             struct spoolss_Notify *data,
2994                                             print_queue_struct *queue,
2995                                             struct spoolss_PrinterInfo2 *pinfo2,
2996                                             TALLOC_CTX *mem_ctx)
2997 {
2998         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2999 }
3000
3001 /*******************************************************************
3002  * fill a notify_info_data with the start time
3003  ********************************************************************/
3004
3005 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3006                                       int snum,
3007                                       struct spoolss_Notify *data,
3008                                       print_queue_struct *queue,
3009                                       struct spoolss_PrinterInfo2 *pinfo2,
3010                                       TALLOC_CTX *mem_ctx)
3011 {
3012         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3013 }
3014
3015 /*******************************************************************
3016  * fill a notify_info_data with the until time
3017  ********************************************************************/
3018
3019 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3020                                       int snum,
3021                                       struct spoolss_Notify *data,
3022                                       print_queue_struct *queue,
3023                                       struct spoolss_PrinterInfo2 *pinfo2,
3024                                       TALLOC_CTX *mem_ctx)
3025 {
3026         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3027 }
3028
3029 /*******************************************************************
3030  * fill a notify_info_data with the status
3031  ********************************************************************/
3032
3033 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3034                                   int snum,
3035                                   struct spoolss_Notify *data,
3036                                   print_queue_struct *queue,
3037                                   struct spoolss_PrinterInfo2 *pinfo2,
3038                                   TALLOC_CTX *mem_ctx)
3039 {
3040         print_status_struct status;
3041
3042         print_queue_length(msg_ctx, snum, &status);
3043         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3044 }
3045
3046 /*******************************************************************
3047  * fill a notify_info_data with the number of jobs queued
3048  ********************************************************************/
3049
3050 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3051                                  int snum,
3052                                  struct spoolss_Notify *data,
3053                                  print_queue_struct *queue,
3054                                  struct spoolss_PrinterInfo2 *pinfo2,
3055                                  TALLOC_CTX *mem_ctx)
3056 {
3057         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3058                 data, print_queue_length(msg_ctx, snum, NULL));
3059 }
3060
3061 /*******************************************************************
3062  * fill a notify_info_data with the average ppm
3063  ********************************************************************/
3064
3065 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3066                                        int snum,
3067                                        struct spoolss_Notify *data,
3068                                        print_queue_struct *queue,
3069                                        struct spoolss_PrinterInfo2 *pinfo2,
3070                                        TALLOC_CTX *mem_ctx)
3071 {
3072         /* always respond 8 pages per minutes */
3073         /* a little hard ! */
3074         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3075 }
3076
3077 /*******************************************************************
3078  * fill a notify_info_data with username
3079  ********************************************************************/
3080
3081 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3082                                     int snum,
3083                                     struct spoolss_Notify *data,
3084                                     print_queue_struct *queue,
3085                                     struct spoolss_PrinterInfo2 *pinfo2,
3086                                     TALLOC_CTX *mem_ctx)
3087 {
3088         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3089 }
3090
3091 /*******************************************************************
3092  * fill a notify_info_data with job status
3093  ********************************************************************/
3094
3095 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3096                                       int snum,
3097                                       struct spoolss_Notify *data,
3098                                       print_queue_struct *queue,
3099                                       struct spoolss_PrinterInfo2 *pinfo2,
3100                                       TALLOC_CTX *mem_ctx)
3101 {
3102         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3103 }
3104
3105 /*******************************************************************
3106  * fill a notify_info_data with job name
3107  ********************************************************************/
3108
3109 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3110                                     int snum,
3111                                     struct spoolss_Notify *data,
3112                                     print_queue_struct *queue,
3113                                     struct spoolss_PrinterInfo2 *pinfo2,
3114                                     TALLOC_CTX *mem_ctx)
3115 {
3116         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3117 }
3118
3119 /*******************************************************************
3120  * fill a notify_info_data with job status
3121  ********************************************************************/
3122
3123 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3124                                              int snum,
3125                                              struct spoolss_Notify *data,
3126                                              print_queue_struct *queue,
3127                                              struct spoolss_PrinterInfo2 *pinfo2,
3128                                              TALLOC_CTX *mem_ctx)
3129 {
3130         /*
3131          * Now we're returning job status codes we just return a "" here. JRA.
3132          */
3133
3134         const char *p = "";
3135
3136 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3137         p = "unknown";
3138
3139         switch (queue->status) {
3140         case LPQ_QUEUED:
3141                 p = "Queued";
3142                 break;
3143         case LPQ_PAUSED:
3144                 p = "";    /* NT provides the paused string */
3145                 break;
3146         case LPQ_SPOOLING:
3147                 p = "Spooling";
3148                 break;
3149         case LPQ_PRINTING:
3150                 p = "Printing";
3151                 break;
3152         }
3153 #endif /* NO LONGER NEEDED. */
3154
3155         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3156 }
3157
3158 /*******************************************************************
3159  * fill a notify_info_data with job time
3160  ********************************************************************/
3161
3162 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3163                                     int snum,
3164                                     struct spoolss_Notify *data,
3165                                     print_queue_struct *queue,
3166                                     struct spoolss_PrinterInfo2 *pinfo2,
3167                                     TALLOC_CTX *mem_ctx)
3168 {
3169         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3170 }
3171
3172 /*******************************************************************
3173  * fill a notify_info_data with job size
3174  ********************************************************************/
3175
3176 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3177                                     int snum,
3178                                     struct spoolss_Notify *data,
3179                                     print_queue_struct *queue,
3180                                     struct spoolss_PrinterInfo2 *pinfo2,
3181                                     TALLOC_CTX *mem_ctx)
3182 {
3183         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3184 }
3185
3186 /*******************************************************************
3187  * fill a notify_info_data with page info
3188  ********************************************************************/
3189 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3190                                        int snum,
3191                                 struct spoolss_Notify *data,
3192                                 print_queue_struct *queue,
3193                                 struct spoolss_PrinterInfo2 *pinfo2,
3194                                 TALLOC_CTX *mem_ctx)
3195 {
3196         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3197 }
3198
3199 /*******************************************************************
3200  * fill a notify_info_data with pages printed info.
3201  ********************************************************************/
3202 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3203                                          int snum,
3204                                 struct spoolss_Notify *data,
3205                                 print_queue_struct *queue,
3206                                 struct spoolss_PrinterInfo2 *pinfo2,
3207                                 TALLOC_CTX *mem_ctx)
3208 {
3209         /* Add code when back-end tracks this */
3210         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3211 }
3212
3213 /*******************************************************************
3214  Fill a notify_info_data with job position.
3215  ********************************************************************/
3216
3217 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3218                                         int snum,
3219                                         struct spoolss_Notify *data,
3220                                         print_queue_struct *queue,
3221                                         struct spoolss_PrinterInfo2 *pinfo2,
3222                                         TALLOC_CTX *mem_ctx)
3223 {
3224         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3225 }
3226
3227 /*******************************************************************
3228  Fill a notify_info_data with submitted time.
3229  ********************************************************************/
3230
3231 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3232                                           int snum,
3233                                           struct spoolss_Notify *data,
3234                                           print_queue_struct *queue,
3235                                           struct spoolss_PrinterInfo2 *pinfo2,
3236                                           TALLOC_CTX *mem_ctx)
3237 {
3238         data->data.string.string = NULL;
3239         data->data.string.size = 0;
3240
3241         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3242                                &data->data.string.string,
3243                                &data->data.string.size);
3244
3245 }
3246
3247 struct s_notify_info_data_table
3248 {
3249         enum spoolss_NotifyType type;
3250         uint16_t field;
3251         const char *name;
3252         enum spoolss_NotifyTable variable_type;
3253         void (*fn) (struct messaging_context *msg_ctx,
3254                     int snum, struct spoolss_Notify *data,
3255                     print_queue_struct *queue,
3256                     struct spoolss_PrinterInfo2 *pinfo2,
3257                     TALLOC_CTX *mem_ctx);
3258 };
3259
3260 /* A table describing the various print notification constants and
3261    whether the notification data is a pointer to a variable sized
3262    buffer, a one value uint32_t or a two value uint32_t. */
3263
3264 static const struct s_notify_info_data_table notify_info_data_table[] =
3265 {
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3292 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3293 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3294 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3295 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3296 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3301 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3302 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3304 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3305 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3306 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3307 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3308 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3309 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3311 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3313 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3314 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3315 };
3316
3317 /*******************************************************************
3318  Return the variable_type of info_data structure.
3319 ********************************************************************/
3320
3321 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3322                                                                   uint16_t field)
3323 {
3324         int i=0;
3325
3326         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3327                 if ( (notify_info_data_table[i].type == type) &&
3328                      (notify_info_data_table[i].field == field) ) {
3329                         return notify_info_data_table[i].variable_type;
3330                 }
3331         }
3332
3333         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3334
3335         return (enum spoolss_NotifyTable) 0;
3336 }
3337
3338 /****************************************************************************
3339 ****************************************************************************/
3340
3341 static bool search_notify(enum spoolss_NotifyType type,
3342                           uint16_t field,
3343                           int *value)
3344 {
3345         int i;
3346
3347         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3348                 if (notify_info_data_table[i].type == type &&
3349                     notify_info_data_table[i].field == field &&
3350                     notify_info_data_table[i].fn != NULL) {
3351                         *value = i;
3352                         return true;
3353                 }
3354         }
3355
3356         return false;
3357 }
3358
3359 /****************************************************************************
3360 ****************************************************************************/
3361
3362 static void construct_info_data(struct spoolss_Notify *info_data,
3363                                 enum spoolss_NotifyType type,
3364                                 uint16_t field, int id)
3365 {
3366         info_data->type                 = type;
3367         info_data->field.field          = field;
3368         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3369         info_data->job_id               = id;
3370 }
3371
3372 /*******************************************************************
3373  *
3374  * fill a notify_info struct with info asked
3375  *
3376  ********************************************************************/
3377
3378 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3379                                           struct printer_handle *print_hnd,
3380                                           struct spoolss_NotifyInfo *info,
3381                                           struct spoolss_PrinterInfo2 *pinfo2,
3382                                           int snum,
3383                                           const struct spoolss_NotifyOptionType *option_type,
3384                                           uint32_t id,
3385                                           TALLOC_CTX *mem_ctx)
3386 {
3387         int field_num,j;
3388         enum spoolss_NotifyType type;
3389         uint16_t field;
3390
3391         struct spoolss_Notify *current_data;
3392
3393         type = option_type->type;
3394
3395         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3396                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3397                 option_type->count, lp_servicename(talloc_tos(), snum)));
3398
3399         for(field_num=0; field_num < option_type->count; field_num++) {
3400                 field = option_type->fields[field_num].field;
3401
3402                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3403
3404                 if (!search_notify(type, field, &j) )
3405                         continue;
3406
3407                 info->notifies = talloc_realloc(info, info->notifies,
3408                                                       struct spoolss_Notify,
3409                                                       info->count + 1);
3410                 if (info->notifies == NULL) {
3411                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3412                         return false;
3413                 }
3414
3415                 current_data = &info->notifies[info->count];
3416
3417                 construct_info_data(current_data, type, field, id);
3418
3419                 DEBUG(10, ("construct_notify_printer_info: "
3420                            "calling [%s]  snum=%d  printername=[%s])\n",
3421                            notify_info_data_table[j].name, snum,
3422                            pinfo2->printername));
3423
3424                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3425                                              NULL, pinfo2, mem_ctx);
3426
3427                 info->count++;
3428         }
3429
3430         return true;
3431 }
3432
3433 /*******************************************************************
3434  *
3435  * fill a notify_info struct with info asked
3436  *
3437  ********************************************************************/
3438
3439 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3440                                        print_queue_struct *queue,
3441                                        struct spoolss_NotifyInfo *info,
3442                                        struct spoolss_PrinterInfo2 *pinfo2,
3443                                        int snum,
3444                                        const struct spoolss_NotifyOptionType *option_type,
3445                                        uint32_t id,
3446                                        TALLOC_CTX *mem_ctx)
3447 {
3448         int field_num,j;
3449         enum spoolss_NotifyType type;
3450         uint16_t field;
3451         struct spoolss_Notify *current_data;
3452
3453         DEBUG(4,("construct_notify_jobs_info\n"));
3454
3455         type = option_type->type;
3456
3457         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3458                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3459                 option_type->count));
3460
3461         for(field_num=0; field_num<option_type->count; field_num++) {
3462                 field = option_type->fields[field_num].field;
3463
3464                 if (!search_notify(type, field, &j) )
3465                         continue;
3466
3467                 info->notifies = talloc_realloc(info, info->notifies,
3468                                                       struct spoolss_Notify,
3469                                                       info->count + 1);
3470                 if (info->notifies == NULL) {
3471                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3472                         return false;
3473                 }
3474
3475                 current_data=&(info->notifies[info->count]);
3476
3477                 construct_info_data(current_data, type, field, id);
3478                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3479                                              queue, pinfo2, mem_ctx);
3480                 info->count++;
3481         }
3482
3483         return true;
3484 }
3485
3486 /*
3487  * JFM: The enumeration is not that simple, it's even non obvious.
3488  *
3489  * let's take an example: I want to monitor the PRINTER SERVER for
3490  * the printer's name and the number of jobs currently queued.
3491  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3492  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3493  *
3494  * I have 3 printers on the back of my server.
3495  *
3496  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3497  * structures.
3498  *   Number     Data                    Id
3499  *      1       printer 1 name          1
3500  *      2       printer 1 cjob          1
3501  *      3       printer 2 name          2
3502  *      4       printer 2 cjob          2
3503  *      5       printer 3 name          3
3504  *      6       printer 3 name          3
3505  *
3506  * that's the print server case, the printer case is even worse.
3507  */
3508
3509 /*******************************************************************
3510  *
3511  * enumerate all printers on the printserver
3512  * fill a notify_info struct with info asked
3513  *
3514  ********************************************************************/
3515
3516 static WERROR printserver_notify_info(struct pipes_struct *p,
3517                                       struct policy_handle *hnd,
3518                                       struct spoolss_NotifyInfo *info,
3519                                       TALLOC_CTX *mem_ctx)
3520 {
3521         int snum;
3522         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3523         int n_services=lp_numservices();
3524         int i;
3525         struct spoolss_NotifyOption *option;
3526         struct spoolss_NotifyOptionType option_type;
3527         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3528         WERROR result;
3529
3530         DEBUG(4,("printserver_notify_info\n"));
3531
3532         if (!Printer)
3533                 return WERR_INVALID_HANDLE;
3534
3535         option = Printer->notify.option;
3536
3537         info->version   = 2;
3538         info->notifies  = NULL;
3539         info->count     = 0;
3540
3541         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3542            sending a ffpcn() request first */
3543
3544         if ( !option )
3545                 return WERR_INVALID_HANDLE;
3546
3547         for (i=0; i<option->count; i++) {
3548                 option_type = option->types[i];
3549
3550                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3551                         continue;
3552
3553                 for (snum = 0; snum < n_services; snum++) {
3554                         if (!lp_browseable(snum) ||
3555                             !lp_snum_ok(snum) ||
3556                             !lp_printable(snum)) {
3557                                 continue; /* skip */
3558                         }
3559
3560                         /* Maybe we should use the SYSTEM session_info here... */
3561                         result = winreg_get_printer_internal(mem_ctx,
3562                                                     get_session_info_system(),
3563                                                     p->msg_ctx,
3564                                                     lp_servicename(talloc_tos(), snum),
3565                                                     &pinfo2);
3566                         if (!W_ERROR_IS_OK(result)) {
3567                                 DEBUG(4, ("printserver_notify_info: "
3568                                           "Failed to get printer [%s]\n",
3569                                           lp_servicename(talloc_tos(), snum)));
3570                                 continue;
3571                         }
3572
3573
3574                         construct_notify_printer_info(p->msg_ctx,
3575                                                       Printer, info,
3576                                                       pinfo2, snum,
3577                                                       &option_type, snum,
3578                                                       mem_ctx);
3579
3580                         TALLOC_FREE(pinfo2);
3581                 }
3582         }
3583
3584 #if 0
3585         /*
3586          * Debugging information, don't delete.
3587          */
3588
3589         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3590         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3591         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3592
3593         for (i=0; i<info->count; i++) {
3594                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3595                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3596                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3597         }
3598 #endif
3599
3600         return WERR_OK;
3601 }
3602
3603 /*******************************************************************
3604  *
3605  * fill a notify_info struct with info asked
3606  *
3607  ********************************************************************/
3608
3609 static WERROR printer_notify_info(struct pipes_struct *p,
3610                                   struct policy_handle *hnd,
3611                                   struct spoolss_NotifyInfo *info,
3612                                   TALLOC_CTX *mem_ctx)
3613 {
3614         int snum;
3615         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3616         int i;
3617         uint32_t id;
3618         struct spoolss_NotifyOption *option;
3619         struct spoolss_NotifyOptionType option_type;
3620         int count,j;
3621         print_queue_struct *queue=NULL;
3622         print_status_struct status;
3623         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3624         WERROR result;
3625         struct tdb_print_db *pdb;
3626
3627         DEBUG(4,("printer_notify_info\n"));
3628
3629         if (!Printer)
3630                 return WERR_INVALID_HANDLE;
3631
3632         option = Printer->notify.option;
3633         id = 0x0;
3634
3635         info->version   = 2;
3636         info->notifies  = NULL;
3637         info->count     = 0;
3638
3639         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3640            sending a ffpcn() request first */
3641
3642         if ( !option )
3643                 return WERR_INVALID_HANDLE;
3644
3645         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3646                 return WERR_INVALID_HANDLE;
3647         }
3648
3649         pdb = get_print_db_byname(Printer->sharename);
3650         if (pdb == NULL) {
3651                 return WERR_INVALID_HANDLE;
3652         }
3653
3654         /* Maybe we should use the SYSTEM session_info here... */
3655         result = winreg_get_printer_internal(mem_ctx,
3656                                     get_session_info_system(),
3657                                     p->msg_ctx,
3658                                     lp_servicename(talloc_tos(), snum), &pinfo2);
3659         if (!W_ERROR_IS_OK(result)) {
3660                 result = WERR_INVALID_HANDLE;
3661                 goto err_pdb_drop;
3662         }
3663
3664         /*
3665          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3666          * correct servername.
3667          */
3668         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3669         if (pinfo2->servername == NULL) {
3670                 result = WERR_NOT_ENOUGH_MEMORY;
3671                 goto err_pdb_drop;
3672         }
3673
3674         for (i = 0; i < option->count; i++) {
3675                 option_type = option->types[i];
3676
3677                 switch (option_type.type) {
3678                 case PRINTER_NOTIFY_TYPE:
3679                         if (construct_notify_printer_info(p->msg_ctx,
3680                                                           Printer, info,
3681                                                           pinfo2, snum,
3682                                                           &option_type, id,
3683                                                           mem_ctx)) {
3684                                 id--;
3685                         }
3686                         break;
3687
3688                 case JOB_NOTIFY_TYPE:
3689
3690                         count = print_queue_status(p->msg_ctx, snum, &queue,
3691                                                    &status);
3692
3693                         for (j = 0; j < count; j++) {
3694                                 uint32_t jobid;
3695                                 jobid = sysjob_to_jobid_pdb(pdb,
3696                                                             queue[j].sysjob);
3697                                 if (jobid == (uint32_t)-1) {
3698                                         DEBUG(2, ("ignoring untracked job %d\n",
3699                                                   queue[j].sysjob));
3700                                         continue;
3701                                 }
3702                                 /* FIXME check return value */
3703                                 construct_notify_jobs_info(p->msg_ctx,
3704                                                            &queue[j], info,
3705                                                            pinfo2, snum,
3706                                                            &option_type,
3707                                                            jobid,
3708                                                            mem_ctx);
3709                         }
3710
3711                         SAFE_FREE(queue);
3712                         break;
3713                 }
3714         }
3715
3716         /*
3717          * Debugging information, don't delete.
3718          */
3719         /*
3720         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3721         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3722         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3723
3724         for (i=0; i<info->count; i++) {
3725                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3726                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3727                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3728         }
3729         */
3730
3731         talloc_free(pinfo2);
3732         result = WERR_OK;
3733 err_pdb_drop:
3734         release_print_db(pdb);
3735         return result;
3736 }
3737
3738 /****************************************************************
3739  _spoolss_RouterRefreshPrinterChangeNotify
3740 ****************************************************************/
3741
3742 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3743                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3744 {
3745         struct spoolss_NotifyInfo *info;
3746
3747         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3748         WERROR result = WERR_INVALID_HANDLE;
3749
3750         /* we always have a spoolss_NotifyInfo struct */
3751         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3752         if (!info) {
3753                 result = WERR_NOT_ENOUGH_MEMORY;
3754                 goto done;
3755         }
3756
3757         *r->out.info = info;
3758
3759         if (!Printer) {
3760                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3761                         "Invalid handle (%s:%u:%u).\n",
3762                         OUR_HANDLE(r->in.handle)));
3763                 goto done;
3764         }
3765
3766         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3767
3768         /*
3769          *      We are now using the change value, and
3770          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3771          *      I don't have a global notification system, I'm sending back all the
3772          *      information even when _NOTHING_ has changed.
3773          */
3774
3775         /* We need to keep track of the change value to send back in
3776            RRPCN replies otherwise our updates are ignored. */
3777
3778         Printer->notify.fnpcn = true;
3779
3780         if (Printer->notify.cli_chan != NULL &&
3781             Printer->notify.cli_chan->active_connections > 0) {
3782                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3783                         "Saving change value in request [%x]\n",
3784                         r->in.change_low));
3785                 Printer->notify.change = r->in.change_low;
3786         }
3787
3788         /* just ignore the spoolss_NotifyOption */
3789
3790         switch (Printer->printer_type) {
3791                 case SPLHND_SERVER:
3792                         result = printserver_notify_info(p, r->in.handle,
3793                                                          info, p->mem_ctx);
3794                         break;
3795
3796                 case SPLHND_PRINTER:
3797                         result = printer_notify_info(p, r->in.handle,
3798                                                      info, p->mem_ctx);
3799                         break;
3800         }
3801
3802         Printer->notify.fnpcn = false;
3803
3804 done:
3805         return result;
3806 }
3807
3808 /********************************************************************
3809  ********************************************************************/
3810
3811 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3812                                  const char *servername,
3813                                  const char *printername,
3814                                  const char **printername_p)
3815 {
3816         /* FIXME: add lp_force_printername() */
3817
3818         if (servername == NULL) {
3819                 *printername_p = talloc_strdup(mem_ctx, printername);
3820                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3821                 return WERR_OK;
3822         }
3823
3824         if (servername[0] == '\\' && servername[1] == '\\') {
3825                 servername += 2;
3826         }
3827
3828         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3829         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3830
3831         return WERR_OK;
3832 }
3833
3834 /********************************************************************
3835  ********************************************************************/
3836
3837 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3838                                           const char *printername)
3839 {
3840         if (dm == NULL) {
3841                 return;
3842         }
3843
3844         dm->devicename = talloc_strndup(dm, printername,
3845                                         MIN(strlen(printername), 31));
3846 }
3847
3848 /********************************************************************
3849  * construct_printer_info_0
3850  * fill a printer_info_0 struct
3851  ********************************************************************/
3852
3853 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3854                                       const struct auth_session_info *session_info,
3855                                       struct messaging_context *msg_ctx,
3856                                       struct spoolss_PrinterInfo2 *info2,
3857                                       const char *servername,
3858                                       struct spoolss_PrinterInfo0 *r,
3859                                       int snum)
3860 {
3861         int count;
3862         struct printer_session_counter *session_counter;
3863         struct timeval setuptime;
3864         print_status_struct status;
3865         WERROR result;
3866
3867         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3868         if (!W_ERROR_IS_OK(result)) {
3869                 return result;
3870         }
3871
3872         if (servername) {
3873                 r->servername = talloc_strdup(mem_ctx, servername);
3874                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3875         } else {
3876                 r->servername = NULL;
3877         }
3878
3879         count = print_queue_length(msg_ctx, snum, &status);
3880
3881         /* check if we already have a counter for this printer */
3882         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3883                 if (session_counter->snum == snum)
3884                         break;
3885         }
3886
3887         /* it's the first time, add it to the list */
3888         if (session_counter == NULL) {
3889                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3890                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3891                 session_counter->snum           = snum;
3892                 session_counter->counter        = 0;
3893                 DLIST_ADD(counter_list, session_counter);
3894         }
3895
3896         /* increment it */
3897         session_counter->counter++;
3898
3899         r->cjobs                        = count;
3900         r->total_jobs                   = 0;
3901         r->total_bytes                  = 0;
3902
3903         get_startup_time(&setuptime);
3904         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3905
3906         /* JFM:
3907          * the global_counter should be stored in a TDB as it's common to all the clients
3908          * and should be zeroed on samba startup
3909          */
3910         r->global_counter               = session_counter->counter;
3911         r->total_pages                  = 0;
3912         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3913         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3914         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3915         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3916         r->spooling                     = 0;
3917         r->max_spooling                 = 0;
3918         r->session_counter              = session_counter->counter;
3919         r->num_error_out_of_paper       = 0x0;
3920         r->num_error_not_ready          = 0x0;          /* number of print failure */
3921         r->job_error                    = 0x0;
3922         r->number_of_processors         = 0x1;
3923         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3924         r->high_part_total_bytes        = 0x0;
3925
3926         /* ChangeID in milliseconds*/
3927         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3928                                     info2->sharename, &r->change_id);
3929
3930         r->last_error                   = WERR_OK;
3931         r->status                       = nt_printq_status(status.status);
3932         r->enumerate_network_printers   = 0x0;
3933         r->c_setprinter                 = 0x0;
3934         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3935         r->processor_level              = 0x6;          /* 6  ???*/
3936         r->ref_ic                       = 0;
3937         r->reserved2                    = 0;
3938         r->reserved3                    = 0;
3939
3940         return WERR_OK;
3941 }
3942
3943
3944 /********************************************************************
3945  * construct_printer_info1
3946  * fill a spoolss_PrinterInfo1 struct
3947 ********************************************************************/
3948
3949 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3950                                       const struct spoolss_PrinterInfo2 *info2,
3951                                       uint32_t flags,
3952                                       const char *servername,
3953                                       struct spoolss_PrinterInfo1 *r,
3954                                       int snum)
3955 {
3956         WERROR result;
3957
3958         r->flags                = flags;
3959
3960         if (info2->comment == NULL || info2->comment[0] == '\0') {
3961                 r->comment      = lp_comment(mem_ctx, snum);
3962         } else {
3963                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3964         }
3965         W_ERROR_HAVE_NO_MEMORY(r->comment);
3966
3967         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3968         if (!W_ERROR_IS_OK(result)) {
3969                 return result;
3970         }
3971
3972         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3973                                                   r->name,
3974                                                   info2->drivername,
3975                                                   r->comment);
3976         W_ERROR_HAVE_NO_MEMORY(r->description);
3977
3978         return WERR_OK;
3979 }
3980
3981 /********************************************************************
3982  * construct_printer_info2
3983  * fill a spoolss_PrinterInfo2 struct
3984 ********************************************************************/
3985
3986 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3987                                       struct messaging_context *msg_ctx,
3988                                       const struct spoolss_PrinterInfo2 *info2,
3989                                       const char *servername,
3990                                       struct spoolss_PrinterInfo2 *r,
3991                                       int snum)
3992 {
3993         int count;
3994         print_status_struct status;
3995         WERROR result;
3996
3997         count = print_queue_length(msg_ctx, snum, &status);
3998
3999         if (servername) {
4000                 r->servername           = talloc_strdup(mem_ctx, servername);
4001                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4002         } else {
4003                 r->servername           = NULL;
4004         }
4005
4006         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4007         if (!W_ERROR_IS_OK(result)) {
4008                 return result;
4009         }
4010
4011         r->sharename            = lp_servicename(mem_ctx, snum);
4012         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4013         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4014         W_ERROR_HAVE_NO_MEMORY(r->portname);
4015         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4016         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4017
4018         if (info2->comment[0] == '\0') {
4019                 r->comment      = lp_comment(mem_ctx, snum);
4020         } else {
4021                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4022         }
4023         W_ERROR_HAVE_NO_MEMORY(r->comment);
4024
4025         r->location     = talloc_strdup(mem_ctx, info2->location);
4026         if (info2->location[0] == '\0') {
4027                 const char *loc = NULL;
4028                 NTSTATUS nt_status;
4029
4030                 nt_status = printer_list_get_printer(mem_ctx,
4031                                                      info2->sharename,
4032                                                      NULL,
4033                                                      &loc,
4034                                                      NULL);
4035                 if (NT_STATUS_IS_OK(nt_status)) {
4036                         if (loc != NULL) {
4037                                 r->location = talloc_strdup(mem_ctx, loc);
4038                         }
4039                 }
4040         }
4041         W_ERROR_HAVE_NO_MEMORY(r->location);
4042
4043         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4044         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4045         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4046         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4047         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4048         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4049         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4050         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4051
4052         r->attributes           = info2->attributes;
4053
4054         r->priority             = info2->priority;
4055         r->defaultpriority      = info2->defaultpriority;
4056         r->starttime            = info2->starttime;
4057         r->untiltime            = info2->untiltime;
4058         r->status               = nt_printq_status(status.status);
4059         r->cjobs                = count;
4060         r->averageppm           = info2->averageppm;
4061
4062         if (info2->devmode != NULL) {
4063                 result = copy_devicemode(mem_ctx,
4064                                          info2->devmode,
4065                                          &r->devmode);
4066                 if (!W_ERROR_IS_OK(result)) {
4067                         return result;
4068                 }
4069         } else if (lp_default_devmode(snum)) {
4070                 result = spoolss_create_default_devmode(mem_ctx,
4071                                                         info2->printername,
4072                                                         &r->devmode);
4073                 if (!W_ERROR_IS_OK(result)) {
4074                         return result;
4075                 }
4076         } else {
4077                 r->devmode = NULL;
4078                 DEBUG(8,("Returning NULL Devicemode!\n"));
4079         }
4080
4081         compose_devicemode_devicename(r->devmode, r->printername);
4082
4083         r->secdesc = NULL;
4084
4085         if (info2->secdesc != NULL) {
4086                 /* don't use talloc_steal() here unless you do a deep steal of all
4087                    the SEC_DESC members */
4088
4089                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4090                 if (r->secdesc == NULL) {
4091                         return WERR_NOT_ENOUGH_MEMORY;
4092                 }
4093         }
4094
4095         return WERR_OK;
4096 }
4097
4098 /********************************************************************
4099  * construct_printer_info3
4100  * fill a spoolss_PrinterInfo3 struct
4101  ********************************************************************/
4102
4103 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4104                                       const struct spoolss_PrinterInfo2 *info2,
4105                                       const char *servername,
4106                                       struct spoolss_PrinterInfo3 *r,
4107                                       int snum)
4108 {
4109         /* These are the components of the SD we are returning. */
4110
4111         if (info2->secdesc != NULL) {
4112                 /* don't use talloc_steal() here unless you do a deep steal of all
4113                    the SEC_DESC members */
4114
4115                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4116                 if (r->secdesc == NULL) {
4117                         return WERR_NOT_ENOUGH_MEMORY;
4118                 }
4119         }
4120
4121         return WERR_OK;
4122 }
4123
4124 /********************************************************************
4125  * construct_printer_info4
4126  * fill a spoolss_PrinterInfo4 struct
4127  ********************************************************************/
4128
4129 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4130                                       const struct spoolss_PrinterInfo2 *info2,
4131                                       const char *servername,
4132                                       struct spoolss_PrinterInfo4 *r,
4133                                       int snum)
4134 {
4135         WERROR result;
4136
4137         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4138         if (!W_ERROR_IS_OK(result)) {
4139                 return result;
4140         }
4141
4142         if (servername) {
4143                 r->servername   = talloc_strdup(mem_ctx, servername);
4144                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4145         } else {
4146                 r->servername = NULL;
4147         }
4148
4149         r->attributes   = info2->attributes;
4150
4151         return WERR_OK;
4152 }
4153
4154 /********************************************************************
4155  * construct_printer_info5
4156  * fill a spoolss_PrinterInfo5 struct
4157  ********************************************************************/
4158
4159 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4160                                       const struct spoolss_PrinterInfo2 *info2,
4161                                       const char *servername,
4162                                       struct spoolss_PrinterInfo5 *r,
4163                                       int snum)
4164 {
4165         WERROR result;
4166
4167         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4168         if (!W_ERROR_IS_OK(result)) {
4169                 return result;
4170         }
4171
4172         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4173         W_ERROR_HAVE_NO_MEMORY(r->portname);
4174
4175         r->attributes   = info2->attributes;
4176
4177         /* these two are not used by NT+ according to MSDN */
4178         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4179         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4180
4181         return WERR_OK;
4182 }
4183
4184 /********************************************************************
4185  * construct_printer_info_6
4186  * fill a spoolss_PrinterInfo6 struct
4187  ********************************************************************/
4188
4189 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4190                                       struct messaging_context *msg_ctx,
4191                                       const struct spoolss_PrinterInfo2 *info2,
4192                                       const char *servername,
4193                                       struct spoolss_PrinterInfo6 *r,
4194                                       int snum)
4195 {
4196         print_status_struct status;
4197
4198         print_queue_length(msg_ctx, snum, &status);
4199
4200         r->status = nt_printq_status(status.status);
4201
4202         return WERR_OK;
4203 }
4204
4205 /********************************************************************
4206  * construct_printer_info7
4207  * fill a spoolss_PrinterInfo7 struct
4208  ********************************************************************/
4209
4210 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4211                                       struct messaging_context *msg_ctx,
4212                                       const char *servername,
4213                                       struct spoolss_PrinterInfo7 *r,
4214                                       int snum)
4215 {
4216         const struct auth_session_info *session_info;
4217         char *printer;
4218         WERROR werr;
4219         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4220         if (tmp_ctx == NULL) {
4221                 return WERR_NOT_ENOUGH_MEMORY;
4222         }
4223
4224         session_info = get_session_info_system();
4225         SMB_ASSERT(session_info != NULL);
4226
4227         printer = lp_servicename(tmp_ctx, snum);
4228         if (printer == NULL) {
4229                 DEBUG(0, ("invalid printer snum %d\n", snum));
4230                 werr = WERR_INVALID_PARAMETER;
4231                 goto out_tmp_free;
4232         }
4233
4234         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4235                                  servername, printer, NULL)) {
4236                 struct GUID guid;
4237                 struct GUID_txt_buf guid_txt;
4238                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4239                                            printer, &guid);
4240                 if (!W_ERROR_IS_OK(werr)) {
4241                         /*
4242                          * If we do not have a GUID entry in the registry, then
4243                          * try to retrieve it from AD and store it now.
4244                          */
4245                         werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4246                                                         &guid);
4247                         if (!W_ERROR_IS_OK(werr)) {
4248                                 DEBUG(1, ("Failed to retrieve GUID for "
4249                                           "printer [%s] from AD - "
4250                                           "Is the the printer still "
4251                                           "published ?\n", printer));
4252                                 goto out_tmp_free;
4253                         }
4254
4255                         werr = nt_printer_guid_store(msg_ctx, printer, guid);
4256                         if (!W_ERROR_IS_OK(werr)) {
4257                                 DEBUG(3, ("failed to store printer %s guid\n",
4258                                           printer));
4259                         }
4260                 }
4261                 r->guid = talloc_strdup_upper(mem_ctx,
4262                                              GUID_buf_string(&guid, &guid_txt));
4263                 r->action = DSPRINT_PUBLISH;
4264         } else {
4265                 r->guid = talloc_strdup(mem_ctx, "");
4266                 r->action = DSPRINT_UNPUBLISH;
4267         }
4268         if (r->guid == NULL) {
4269                 werr = WERR_NOT_ENOUGH_MEMORY;
4270                 goto out_tmp_free;
4271         }
4272
4273         werr = WERR_OK;
4274 out_tmp_free:
4275         talloc_free(tmp_ctx);
4276         return werr;
4277 }
4278
4279 /********************************************************************
4280  * construct_printer_info8
4281  * fill a spoolss_PrinterInfo8 struct
4282  ********************************************************************/
4283
4284 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4285                                       const struct spoolss_PrinterInfo2 *info2,
4286                                       const char *servername,
4287                                       struct spoolss_DeviceModeInfo *r,
4288                                       int snum)
4289 {
4290         WERROR result;
4291         const char *printername;
4292
4293         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4294         if (!W_ERROR_IS_OK(result)) {
4295                 return result;
4296         }
4297
4298         if (info2->devmode != NULL) {
4299                 result = copy_devicemode(mem_ctx,
4300                                          info2->devmode,
4301                                          &r->devmode);
4302                 if (!W_ERROR_IS_OK(result)) {
4303                         return result;
4304                 }
4305         } else if (lp_default_devmode(snum)) {
4306                 result = spoolss_create_default_devmode(mem_ctx,
4307                                                         info2->printername,
4308                                                         &r->devmode);
4309                 if (!W_ERROR_IS_OK(result)) {
4310                         return result;
4311                 }
4312         } else {
4313                 r->devmode = NULL;
4314                 DEBUG(8,("Returning NULL Devicemode!\n"));
4315         }
4316
4317         compose_devicemode_devicename(r->devmode, printername);
4318
4319         return WERR_OK;
4320 }
4321
4322 /********************************************************************
4323  Spoolss_enumprinters.
4324 ********************************************************************/
4325
4326 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4327                                            const struct auth_session_info *session_info,
4328                                            struct messaging_context *msg_ctx,
4329                                            const char *servername,
4330                                            uint32_t level,
4331                                            uint32_t flags,
4332                                            union spoolss_PrinterInfo **info_p,
4333                                            uint32_t *count_p)
4334 {
4335         int snum;
4336         int n_services;
4337         union spoolss_PrinterInfo *info = NULL;
4338         uint32_t count = 0;
4339         WERROR result = WERR_OK;
4340         struct dcerpc_binding_handle *b = NULL;
4341         TALLOC_CTX *tmp_ctx = NULL;
4342
4343         tmp_ctx = talloc_new(mem_ctx);
4344         if (!tmp_ctx) {
4345                 return WERR_NOT_ENOUGH_MEMORY;
4346         }
4347
4348         /*
4349          * printer shares are updated on client enumeration. The background
4350          * printer process updates printer_list.tdb at regular intervals.
4351          */
4352         become_root();
4353         delete_and_reload_printers(server_event_context(), msg_ctx);
4354         unbecome_root();
4355
4356         n_services = lp_numservices();
4357         *count_p = 0;
4358         *info_p = NULL;
4359
4360         for (snum = 0; snum < n_services; snum++) {
4361
4362                 const char *printer;
4363                 struct spoolss_PrinterInfo2 *info2;
4364
4365                 if (!snum_is_shared_printer(snum)) {
4366                         continue;
4367                 }
4368
4369                 printer = lp_const_servicename(snum);
4370
4371                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4372                         printer, snum));
4373
4374                 if (b == NULL) {
4375                         result = winreg_printer_binding_handle(tmp_ctx,
4376                                                                session_info,
4377                                                                msg_ctx,
4378                                                                &b);
4379                         if (!W_ERROR_IS_OK(result)) {
4380                                 goto out;
4381                         }
4382                 }
4383
4384                 result = winreg_create_printer(tmp_ctx, b,
4385                                                printer);
4386                 if (!W_ERROR_IS_OK(result)) {
4387                         goto out;
4388                 }
4389
4390                 info = talloc_realloc(tmp_ctx, info,
4391                                             union spoolss_PrinterInfo,
4392                                             count + 1);
4393                 if (!info) {
4394                         result = WERR_NOT_ENOUGH_MEMORY;
4395                         goto out;
4396                 }
4397
4398                 result = winreg_get_printer(tmp_ctx, b,
4399                                             printer, &info2);
4400                 if (!W_ERROR_IS_OK(result)) {
4401                         goto out;
4402                 }
4403
4404                 switch (level) {
4405                 case 0:
4406                         result = construct_printer_info0(info, session_info,
4407                                                          msg_ctx, info2,
4408                                                          servername,
4409                                                          &info[count].info0, snum);
4410                         break;
4411                 case 1:
4412                         result = construct_printer_info1(info, info2, flags,
4413                                                          servername,
4414                                                          &info[count].info1, snum);
4415                         break;
4416                 case 2:
4417                         result = construct_printer_info2(info, msg_ctx, info2,
4418                                                          servername,
4419                                                          &info[count].info2, snum);
4420                         break;
4421                 case 4:
4422                         result = construct_printer_info4(info, info2,
4423                                                          servername,
4424                                                          &info[count].info4, snum);
4425                         break;
4426                 case 5:
4427                         result = construct_printer_info5(info, info2,
4428                                                          servername,
4429                                                          &info[count].info5, snum);
4430                         break;
4431
4432                 default:
4433                         result = WERR_INVALID_LEVEL;
4434                         goto out;
4435                 }
4436
4437                 if (!W_ERROR_IS_OK(result)) {
4438                         goto out;
4439                 }
4440
4441                 count++;
4442         }
4443
4444 out:
4445         if (W_ERROR_IS_OK(result)) {
4446                 *info_p = talloc_move(mem_ctx, &info);
4447                 *count_p = count;
4448         }
4449
4450         talloc_free(tmp_ctx);
4451
4452         return result;
4453 }
4454
4455 /********************************************************************
4456  * handle enumeration of printers at level 0
4457  ********************************************************************/
4458
4459 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4460                                   const struct auth_session_info *session_info,
4461                                   struct messaging_context *msg_ctx,
4462                                   uint32_t flags,
4463                                   const char *servername,
4464                                   union spoolss_PrinterInfo **info,
4465                                   uint32_t *count)
4466 {
4467         DEBUG(4,("enum_all_printers_info_0\n"));
4468
4469         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4470                                             servername, 0, flags, info, count);
4471 }
4472
4473
4474 /********************************************************************
4475 ********************************************************************/
4476
4477 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4478                                        const struct auth_session_info *session_info,
4479                                        struct messaging_context *msg_ctx,
4480                                        const char *servername,
4481                                        uint32_t flags,
4482                                        union spoolss_PrinterInfo **info,
4483                                        uint32_t *count)
4484 {
4485         DEBUG(4,("enum_all_printers_info_1\n"));
4486
4487         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4488                                             servername, 1, flags, info, count);
4489 }
4490
4491 /********************************************************************
4492  enum_all_printers_info_1_local.
4493 *********************************************************************/
4494
4495 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4496                                              const struct auth_session_info *session_info,
4497                                              struct messaging_context *msg_ctx,
4498                                              const char *servername,
4499                                              union spoolss_PrinterInfo **info,
4500                                              uint32_t *count)
4501 {
4502         DEBUG(4,("enum_all_printers_info_1_local\n"));
4503
4504         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4505                                         servername, PRINTER_ENUM_ICON8, info, count);
4506 }
4507
4508 /********************************************************************
4509  enum_all_printers_info_1_name.
4510 *********************************************************************/
4511
4512 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4513                                             const struct auth_session_info *session_info,
4514                                             struct messaging_context *msg_ctx,
4515                                             const char *servername,
4516                                             union spoolss_PrinterInfo **info,
4517                                             uint32_t *count)
4518 {
4519         const char *s = servername;
4520
4521         DEBUG(4,("enum_all_printers_info_1_name\n"));
4522
4523         if (servername != NULL &&
4524             (servername[0] == '\\') && (servername[1] == '\\')) {
4525                 s = servername + 2;
4526         }
4527
4528         if (!is_myname_or_ipaddr(s)) {
4529                 return WERR_INVALID_NAME;
4530         }
4531
4532         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4533                                         servername, PRINTER_ENUM_ICON8, info, count);
4534 }
4535
4536 /********************************************************************
4537  enum_all_printers_info_1_network.
4538 *********************************************************************/
4539
4540 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4541                                                const struct auth_session_info *session_info,
4542                                                struct messaging_context *msg_ctx,
4543                                                const char *servername,
4544                                                union spoolss_PrinterInfo **info,
4545                                                uint32_t *count)
4546 {
4547         const char *s = servername;
4548
4549         DEBUG(4,("enum_all_printers_info_1_network\n"));
4550
4551         /* If we respond to a enum_printers level 1 on our name with flags
4552            set to PRINTER_ENUM_REMOTE with a list of printers then these
4553            printers incorrectly appear in the APW browse list.
4554            Specifically the printers for the server appear at the workgroup
4555            level where all the other servers in the domain are
4556            listed. Windows responds to this call with a
4557            WERR_CAN_NOT_COMPLETE so we should do the same. */
4558
4559         if (servername != NULL &&
4560             (servername[0] == '\\') && (servername[1] == '\\')) {
4561                  s = servername + 2;
4562         }
4563
4564         if (is_myname_or_ipaddr(s)) {
4565                  return WERR_CAN_NOT_COMPLETE;
4566         }
4567
4568         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4569                                         servername, PRINTER_ENUM_NAME, info, count);
4570 }
4571
4572 /********************************************************************
4573  * api_spoolss_enumprinters
4574  *
4575  * called from api_spoolss_enumprinters (see this to understand)
4576  ********************************************************************/
4577
4578 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4579                                        const struct auth_session_info *session_info,
4580                                        struct messaging_context *msg_ctx,
4581                                        const char *servername,
4582                                        union spoolss_PrinterInfo **info,
4583                                        uint32_t *count)
4584 {
4585         DEBUG(4,("enum_all_printers_info_2\n"));
4586
4587         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4588                                             servername, 2, 0, info, count);
4589 }
4590
4591 /********************************************************************
4592  * handle enumeration of printers at level 1
4593  ********************************************************************/
4594
4595 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4596                                   const struct auth_session_info *session_info,
4597                                   struct messaging_context *msg_ctx,
4598                                   uint32_t flags,
4599                                   const char *servername,
4600                                   union spoolss_PrinterInfo **info,
4601                                   uint32_t *count)
4602 {
4603         /* Not all the flags are equals */
4604
4605         if (flags & PRINTER_ENUM_LOCAL) {
4606                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4607                                                       msg_ctx, servername, info, count);
4608         }
4609
4610         if (flags & PRINTER_ENUM_NAME) {
4611                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4612                                                      msg_ctx, servername, info,
4613                                                      count);
4614         }
4615
4616         if (flags & PRINTER_ENUM_NETWORK) {
4617                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4618                                                         msg_ctx, servername, info,
4619                                                         count);
4620         }
4621
4622         return WERR_OK; /* NT4sp5 does that */
4623 }
4624
4625 /********************************************************************
4626  * handle enumeration of printers at level 2
4627  ********************************************************************/
4628
4629 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4630                                   const struct auth_session_info *session_info,
4631                                   struct messaging_context *msg_ctx,
4632                                   uint32_t flags,
4633                                   const char *servername,
4634                                   union spoolss_PrinterInfo **info,
4635                                   uint32_t *count)
4636 {
4637         if (flags & PRINTER_ENUM_LOCAL) {
4638
4639                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4640                                                 servername,
4641                                                 info, count);
4642         }
4643
4644         if (flags & PRINTER_ENUM_NAME) {
4645                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4646                         return WERR_INVALID_NAME;
4647                 }
4648
4649                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4650                                                 servername,
4651                                                 info, count);
4652         }
4653
4654         if (flags & PRINTER_ENUM_REMOTE) {
4655                 return WERR_INVALID_LEVEL;
4656         }
4657
4658         return WERR_OK;
4659 }
4660
4661 /********************************************************************
4662  * handle enumeration of printers at level 4
4663  ********************************************************************/
4664
4665 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4666                                   const struct auth_session_info *session_info,
4667                                   struct messaging_context *msg_ctx,
4668                                   uint32_t flags,
4669                                   const char *servername,
4670                                   union spoolss_PrinterInfo **info,
4671                                   uint32_t *count)
4672 {
4673         DEBUG(4,("enum_all_printers_info_4\n"));
4674
4675         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4676                                             servername, 4, flags, info, count);
4677 }
4678
4679
4680 /********************************************************************
4681  * handle enumeration of printers at level 5
4682  ********************************************************************/
4683
4684 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4685                                   const struct auth_session_info *session_info,
4686                                   struct messaging_context *msg_ctx,
4687                                   uint32_t flags,
4688                                   const char *servername,
4689                                   union spoolss_PrinterInfo **info,
4690                                   uint32_t *count)
4691 {
4692         DEBUG(4,("enum_all_printers_info_5\n"));
4693
4694         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4695                                             servername, 5, flags, info, count);
4696 }
4697
4698 /****************************************************************
4699  _spoolss_EnumPrinters
4700 ****************************************************************/
4701
4702 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4703                              struct spoolss_EnumPrinters *r)
4704 {
4705         const struct auth_session_info *session_info = get_session_info_system();
4706         WERROR result;
4707
4708         /* that's an [in out] buffer */
4709
4710         if (!r->in.buffer && (r->in.offered != 0)) {
4711                 return WERR_INVALID_PARAMETER;
4712         }
4713
4714         DEBUG(4,("_spoolss_EnumPrinters\n"));
4715
4716         *r->out.needed = 0;
4717         *r->out.count = 0;
4718         *r->out.info = NULL;
4719
4720         /*
4721          * Level 1:
4722          *          flags==PRINTER_ENUM_NAME
4723          *           if name=="" then enumerates all printers
4724          *           if name!="" then enumerate the printer
4725          *          flags==PRINTER_ENUM_REMOTE
4726          *          name is NULL, enumerate printers
4727          * Level 2: name!="" enumerates printers, name can't be NULL
4728          * Level 3: doesn't exist
4729          * Level 4: does a local registry lookup
4730          * Level 5: same as Level 2
4731          */
4732
4733         if (r->in.server && r->in.server[0] == '\0') {
4734                 r->in.server = NULL;
4735         }
4736
4737         switch (r->in.level) {
4738         case 0:
4739                 result = enumprinters_level0(p->mem_ctx, session_info,
4740                                              p->msg_ctx, r->in.flags,
4741                                              r->in.server,
4742                                              r->out.info, r->out.count);
4743                 break;
4744         case 1:
4745                 result = enumprinters_level1(p->mem_ctx, session_info,
4746                                              p->msg_ctx, r->in.flags,
4747                                              r->in.server,
4748                                              r->out.info, r->out.count);
4749                 break;
4750         case 2:
4751                 result = enumprinters_level2(p->mem_ctx, session_info,
4752                                              p->msg_ctx, r->in.flags,
4753                                              r->in.server,
4754                                              r->out.info, r->out.count);
4755                 break;
4756         case 4:
4757                 result = enumprinters_level4(p->mem_ctx, session_info,
4758                                              p->msg_ctx, r->in.flags,
4759                                              r->in.server,
4760                                              r->out.info, r->out.count);
4761                 break;
4762         case 5:
4763                 result = enumprinters_level5(p->mem_ctx, session_info,
4764                                              p->msg_ctx, r->in.flags,
4765                                              r->in.server,
4766                                              r->out.info, r->out.count);
4767                 break;
4768         default:
4769                 return WERR_INVALID_LEVEL;
4770         }
4771
4772         if (!W_ERROR_IS_OK(result)) {
4773                 return result;
4774         }
4775
4776         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4777                                                      spoolss_EnumPrinters,
4778                                                      *r->out.info, r->in.level,
4779                                                      *r->out.count);
4780         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4781         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4782
4783         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4784 }
4785
4786 /****************************************************************
4787  _spoolss_GetPrinter
4788 ****************************************************************/
4789
4790 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4791                            struct spoolss_GetPrinter *r)
4792 {
4793         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4794         struct spoolss_PrinterInfo2 *info2 = NULL;
4795         WERROR result = WERR_OK;
4796         int snum;
4797
4798         /* that's an [in out] buffer */
4799
4800         if (!r->in.buffer && (r->in.offered != 0)) {
4801                 result = WERR_INVALID_PARAMETER;
4802                 goto err_info_free;
4803         }
4804
4805         *r->out.needed = 0;
4806
4807         if (Printer == NULL) {
4808                 result = WERR_INVALID_HANDLE;
4809                 goto err_info_free;
4810         }
4811
4812         if (Printer->printer_type == SPLHND_SERVER) {
4813
4814                 struct dcerpc_binding_handle *b;
4815
4816                 if (r->in.level != 3) {
4817                         result = WERR_INVALID_LEVEL;
4818                         goto err_info_free;
4819                 }
4820
4821                 result = winreg_printer_binding_handle(p->mem_ctx,
4822                                                        get_session_info_system(),
4823                                                        p->msg_ctx,
4824                                                        &b);
4825                 if (!W_ERROR_IS_OK(result)) {
4826                         goto err_info_free;
4827                 }
4828
4829                 result = winreg_get_printserver_secdesc(p->mem_ctx,
4830                                                         b,
4831                                                         &r->out.info->info3.secdesc);
4832                 if (!W_ERROR_IS_OK(result)) {
4833                         goto err_info_free;
4834                 }
4835
4836                 goto done;
4837         }
4838
4839         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4840                 result = WERR_INVALID_HANDLE;
4841                 goto err_info_free;
4842         }
4843
4844         result = winreg_get_printer_internal(p->mem_ctx,
4845                                     get_session_info_system(),
4846                                     p->msg_ctx,
4847                                     lp_const_servicename(snum),
4848                                     &info2);
4849         if (!W_ERROR_IS_OK(result)) {
4850                 goto err_info_free;
4851         }
4852
4853         switch (r->in.level) {
4854         case 0:
4855                 result = construct_printer_info0(p->mem_ctx,
4856                                                  get_session_info_system(),
4857                                                  p->msg_ctx,
4858                                                  info2,
4859                                                  Printer->servername,
4860                                                  &r->out.info->info0,
4861                                                  snum);
4862                 break;
4863         case 1:
4864                 result = construct_printer_info1(p->mem_ctx, info2,
4865                                                  PRINTER_ENUM_ICON8,
4866                                                  Printer->servername,
4867                                                  &r->out.info->info1, snum);
4868                 break;
4869         case 2:
4870                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4871                                                  Printer->servername,
4872                                                  &r->out.info->info2, snum);
4873                 break;
4874         case 3:
4875                 result = construct_printer_info3(p->mem_ctx, info2,
4876                                                  Printer->servername,
4877                                                  &r->out.info->info3, snum);
4878                 break;
4879         case 4:
4880                 result = construct_printer_info4(p->mem_ctx, info2,
4881                                                  Printer->servername,
4882                                                  &r->out.info->info4, snum);
4883                 break;
4884         case 5:
4885                 result = construct_printer_info5(p->mem_ctx, info2,
4886                                                  Printer->servername,
4887                                                  &r->out.info->info5, snum);
4888                 break;
4889         case 6:
4890                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4891                                                  Printer->servername,
4892                                                  &r->out.info->info6, snum);
4893                 break;
4894         case 7:
4895                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4896                                                  Printer->servername,
4897                                                  &r->out.info->info7, snum);
4898                 break;
4899         case 8:
4900                 result = construct_printer_info8(p->mem_ctx, info2,
4901                                                  Printer->servername,
4902                                                  &r->out.info->info8, snum);
4903                 break;
4904         default:
4905                 result = WERR_INVALID_LEVEL;
4906                 break;
4907         }
4908         TALLOC_FREE(info2);
4909
4910         if (!W_ERROR_IS_OK(result)) {
4911                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4912                           r->in.level, win_errstr(result)));
4913                 goto err_info_free;
4914         }
4915  done:
4916         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4917                                                r->out.info, r->in.level);
4918         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4919
4920         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4921
4922 err_info_free:
4923         TALLOC_FREE(r->out.info);
4924         return result;
4925 }
4926
4927 /********************************************************************
4928  ********************************************************************/
4929
4930 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4931         do { \
4932                 if (in && strlen(in)) { \
4933                         out = talloc_strdup(mem_ctx, in); \
4934                 } else { \
4935                         out = talloc_strdup(mem_ctx, ""); \
4936                 } \
4937                 W_ERROR_HAVE_NO_MEMORY(out); \
4938         } while (0);
4939
4940 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4941         do { \
4942                 if (in && strlen(in)) { \
4943                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4944                 } else { \
4945                         out = talloc_strdup(mem_ctx, ""); \
4946                 } \
4947                 W_ERROR_HAVE_NO_MEMORY(out); \
4948         } while (0);
4949
4950 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4951                                                   const char **string_array,
4952                                                   const char ***presult,
4953                                                   const char *cservername,
4954                                                   const char *arch,
4955                                                   int version)
4956 {
4957         int i;
4958         size_t num_strings = 0;
4959         const char **array = NULL;
4960
4961         if (string_array == NULL) {
4962                 return WERR_INVALID_PARAMETER;
4963         }
4964
4965         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4966                 const char *str = NULL;
4967
4968                 if (cservername == NULL || arch == NULL) {
4969                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4970                 } else {
4971                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4972                 }
4973
4974                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4975                         TALLOC_FREE(array);
4976                         return WERR_NOT_ENOUGH_MEMORY;
4977                 }
4978         }
4979
4980         if (i > 0) {
4981                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4982                              &array, &num_strings);
4983         }
4984
4985         if (presult != NULL) {
4986                 *presult = array;
4987         } else {
4988                 talloc_free(array);
4989         }
4990
4991         return WERR_OK;
4992 }
4993
4994 /********************************************************************
4995  * fill a spoolss_DriverInfo1 struct
4996  ********************************************************************/
4997
4998 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4999                                         struct spoolss_DriverInfo1 *r,
5000                                         const struct spoolss_DriverInfo8 *driver,
5001                                         const char *servername)
5002 {
5003         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5004         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5005
5006         return WERR_OK;
5007 }
5008
5009 /********************************************************************
5010  * fill a spoolss_DriverInfo2 struct
5011  ********************************************************************/
5012
5013 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5014                                         struct spoolss_DriverInfo2 *r,
5015                                         const struct spoolss_DriverInfo8 *driver,
5016                                         const char *servername)
5017
5018 {
5019         const char *cservername = canon_servername(servername);
5020
5021         r->version              = driver->version;
5022
5023         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5024         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5025         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5026         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5027
5028         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5029                                driver->architecture,
5030                                driver->version,
5031                                driver->driver_path,
5032                                r->driver_path);
5033
5034         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5035                                driver->architecture,
5036                                driver->version,
5037                                driver->data_file,
5038                                r->data_file);
5039
5040         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5041                                driver->architecture,
5042                                driver->version,
5043                                driver->config_file,
5044                                r->config_file);
5045
5046         return WERR_OK;
5047 }
5048
5049 /********************************************************************
5050  * fill a spoolss_DriverInfo3 struct
5051  ********************************************************************/
5052
5053 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5054                                         struct spoolss_DriverInfo3 *r,
5055                                         const struct spoolss_DriverInfo8 *driver,
5056                                         const char *servername)
5057 {
5058         const char *cservername = canon_servername(servername);
5059
5060         r->version              = driver->version;
5061
5062         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5063         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5064         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5065         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5066
5067         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5068                                driver->architecture,
5069                                driver->version,
5070                                driver->driver_path,
5071                                r->driver_path);
5072
5073         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5074                                driver->architecture,
5075                                driver->version,
5076                                driver->data_file,
5077                                r->data_file);
5078
5079         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5080                                driver->architecture,
5081                                driver->version,
5082                                driver->config_file,
5083                                r->config_file);
5084
5085         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5086                                driver->architecture,
5087                                driver->version,
5088                                driver->help_file,
5089                                r->help_file);
5090
5091         FILL_DRIVER_STRING(mem_ctx,
5092                            driver->monitor_name,
5093                            r->monitor_name);
5094
5095         FILL_DRIVER_STRING(mem_ctx,
5096                            driver->default_datatype,
5097                            r->default_datatype);
5098
5099         return string_array_from_driver_info(mem_ctx,
5100                                              driver->dependent_files,
5101                                              &r->dependent_files,
5102                                              cservername,
5103                                              driver->architecture,
5104                                              driver->version);
5105 }
5106
5107 /********************************************************************
5108  * fill a spoolss_DriverInfo4 struct
5109  ********************************************************************/
5110
5111 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5112                                         struct spoolss_DriverInfo4 *r,
5113                                         const struct spoolss_DriverInfo8 *driver,
5114                                         const char *servername)
5115 {
5116         const char *cservername = canon_servername(servername);
5117         WERROR result;
5118
5119         r->version              = driver->version;
5120
5121         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5122         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5123         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5124         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5125
5126         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5127                                driver->architecture,
5128                                driver->version,
5129                                driver->driver_path,
5130                                r->driver_path);
5131
5132         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5133                                driver->architecture,
5134                                driver->version,
5135                                driver->data_file,
5136                                r->data_file);
5137
5138         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5139                                driver->architecture,
5140                                driver->version,
5141                                driver->config_file,
5142                                r->config_file);
5143
5144         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5145                                driver->architecture,
5146                                driver->version,
5147                                driver->help_file,
5148                                r->help_file);
5149
5150         result = string_array_from_driver_info(mem_ctx,
5151                                                driver->dependent_files,
5152                                                &r->dependent_files,
5153                                                cservername,
5154                                                driver->architecture,
5155                                                driver->version);
5156         if (!W_ERROR_IS_OK(result)) {
5157                 return result;
5158         }
5159
5160         FILL_DRIVER_STRING(mem_ctx,
5161                            driver->monitor_name,
5162                            r->monitor_name);
5163
5164         FILL_DRIVER_STRING(mem_ctx,
5165                            driver->default_datatype,
5166                            r->default_datatype);
5167
5168
5169         result = string_array_from_driver_info(mem_ctx,
5170                                                driver->previous_names,
5171                                                &r->previous_names,
5172                                                NULL, NULL, 0);
5173
5174         return result;
5175 }
5176
5177 /********************************************************************
5178  * fill a spoolss_DriverInfo5 struct
5179  ********************************************************************/
5180
5181 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5182                                         struct spoolss_DriverInfo5 *r,
5183                                         const struct spoolss_DriverInfo8 *driver,
5184                                         const char *servername)
5185 {
5186         const char *cservername = canon_servername(servername);
5187
5188         r->version              = driver->version;
5189
5190         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5191         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5192         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5193         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5194
5195         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5196                                driver->architecture,
5197                                driver->version,
5198                                driver->driver_path,
5199                                r->driver_path);
5200
5201         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5202                                driver->architecture,
5203                                driver->version,
5204                                driver->data_file,
5205                                r->data_file);
5206
5207         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5208                                driver->architecture,
5209                                driver->version,
5210                                driver->config_file,
5211                                r->config_file);
5212
5213         r->driver_attributes    = 0;
5214         r->config_version       = 0;
5215         r->driver_version       = 0;
5216
5217         return WERR_OK;
5218 }
5219 /********************************************************************
5220  * fill a spoolss_DriverInfo6 struct
5221  ********************************************************************/
5222
5223 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5224                                         struct spoolss_DriverInfo6 *r,
5225                                         const struct spoolss_DriverInfo8 *driver,
5226                                         const char *servername)
5227 {
5228         const char *cservername = canon_servername(servername);
5229         WERROR result;
5230
5231         r->version              = driver->version;
5232
5233         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5234         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5235         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5236         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5237
5238         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5239                                driver->architecture,
5240                                driver->version,
5241                                driver->driver_path,
5242                                r->driver_path);
5243
5244         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5245                                driver->architecture,
5246                                driver->version,
5247                                driver->data_file,
5248                                r->data_file);
5249
5250         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5251                                driver->architecture,
5252                                driver->version,
5253                                driver->config_file,
5254                                r->config_file);
5255
5256         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5257                                driver->architecture,
5258                                driver->version,
5259                                driver->help_file,
5260                                r->help_file);
5261
5262         FILL_DRIVER_STRING(mem_ctx,
5263                            driver->monitor_name,
5264                            r->monitor_name);
5265
5266         FILL_DRIVER_STRING(mem_ctx,
5267                            driver->default_datatype,
5268                            r->default_datatype);
5269
5270         result = string_array_from_driver_info(mem_ctx,
5271                                                driver->dependent_files,
5272                                                &r->dependent_files,
5273                                                cservername,
5274                                                driver->architecture,
5275                                                driver->version);
5276         if (!W_ERROR_IS_OK(result)) {
5277                 return result;
5278         }
5279
5280         result = string_array_from_driver_info(mem_ctx,
5281                                                driver->previous_names,
5282                                                &r->previous_names,
5283                                                NULL, NULL, 0);
5284         if (!W_ERROR_IS_OK(result)) {
5285                 return result;
5286         }
5287
5288         r->driver_date          = driver->driver_date;
5289         r->driver_version       = driver->driver_version;
5290
5291         FILL_DRIVER_STRING(mem_ctx,
5292                            driver->manufacturer_name,
5293                            r->manufacturer_name);
5294         FILL_DRIVER_STRING(mem_ctx,
5295                            driver->manufacturer_url,
5296                            r->manufacturer_url);
5297         FILL_DRIVER_STRING(mem_ctx,
5298                            driver->hardware_id,
5299                            r->hardware_id);
5300         FILL_DRIVER_STRING(mem_ctx,
5301                            driver->provider,
5302                            r->provider);
5303
5304         return WERR_OK;
5305 }
5306
5307 /********************************************************************
5308  * fill a spoolss_DriverInfo8 struct
5309  ********************************************************************/
5310
5311 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5312                                         struct spoolss_DriverInfo8 *r,
5313                                         const struct spoolss_DriverInfo8 *driver,
5314                                         const char *servername)
5315 {
5316         const char *cservername = canon_servername(servername);
5317         WERROR result;
5318
5319         r->version              = driver->version;
5320
5321         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5322         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5323         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5324         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5325
5326         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5327                                driver->architecture,
5328                                driver->version,
5329                                driver->driver_path,
5330                                r->driver_path);
5331
5332         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5333                                driver->architecture,
5334                                driver->version,
5335                                driver->data_file,
5336                                r->data_file);
5337
5338         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5339                                driver->architecture,
5340                                driver->version,
5341                                driver->config_file,
5342                                r->config_file);
5343
5344         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5345                                driver->architecture,
5346                                driver->version,
5347                                driver->help_file,
5348                                r->help_file);
5349
5350         FILL_DRIVER_STRING(mem_ctx,
5351                            driver->monitor_name,
5352                            r->monitor_name);
5353
5354         FILL_DRIVER_STRING(mem_ctx,
5355                            driver->default_datatype,
5356                            r->default_datatype);
5357
5358         result = string_array_from_driver_info(mem_ctx,
5359                                                driver->dependent_files,
5360                                                &r->dependent_files,
5361                                                cservername,
5362                                                driver->architecture,
5363                                                driver->version);
5364         if (!W_ERROR_IS_OK(result)) {
5365                 return result;
5366         }
5367
5368         result = string_array_from_driver_info(mem_ctx,
5369                                                driver->previous_names,
5370                                                &r->previous_names,
5371                                                NULL, NULL, 0);
5372         if (!W_ERROR_IS_OK(result)) {
5373                 return result;
5374         }
5375
5376         r->driver_date          = driver->driver_date;
5377         r->driver_version       = driver->driver_version;
5378
5379         FILL_DRIVER_STRING(mem_ctx,
5380                            driver->manufacturer_name,
5381                            r->manufacturer_name);
5382         FILL_DRIVER_STRING(mem_ctx,
5383                            driver->manufacturer_url,
5384                            r->manufacturer_url);
5385         FILL_DRIVER_STRING(mem_ctx,
5386                            driver->hardware_id,
5387                            r->hardware_id);
5388         FILL_DRIVER_STRING(mem_ctx,
5389                            driver->provider,
5390                            r->provider);
5391
5392         FILL_DRIVER_STRING(mem_ctx,
5393                            driver->print_processor,
5394                            r->print_processor);
5395         FILL_DRIVER_STRING(mem_ctx,
5396                            driver->vendor_setup,
5397                            r->vendor_setup);
5398
5399         result = string_array_from_driver_info(mem_ctx,
5400                                                driver->color_profiles,
5401                                                &r->color_profiles,
5402                                                NULL, NULL, 0);
5403         if (!W_ERROR_IS_OK(result)) {
5404                 return result;
5405         }
5406
5407         FILL_DRIVER_STRING(mem_ctx,
5408                            driver->inf_path,
5409                            r->inf_path);
5410
5411         r->printer_driver_attributes    = driver->printer_driver_attributes;
5412
5413         result = string_array_from_driver_info(mem_ctx,
5414                                                driver->core_driver_dependencies,
5415                                                &r->core_driver_dependencies,
5416                                                NULL, NULL, 0);
5417         if (!W_ERROR_IS_OK(result)) {
5418                 return result;
5419         }
5420
5421         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5422         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5423
5424         return WERR_OK;
5425 }
5426
5427 #if 0 /* disabled until marshalling issues are resolved - gd */
5428 /********************************************************************
5429  ********************************************************************/
5430
5431 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5432                                           struct spoolss_DriverFileInfo *r,
5433                                           const char *cservername,
5434                                           const char *file_name,
5435                                           enum spoolss_DriverFileType file_type,
5436                                           uint32_t file_version)
5437 {
5438         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5439                                           cservername, file_name);
5440         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5441         r->file_type    = file_type;
5442         r->file_version = file_version;
5443
5444         return WERR_OK;
5445 }
5446
5447 /********************************************************************
5448  ********************************************************************/
5449
5450 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5451                                                  const struct spoolss_DriverInfo8 *driver,
5452                                                  const char *cservername,
5453                                                  struct spoolss_DriverFileInfo **info_p,
5454                                                  uint32_t *count_p)
5455 {
5456         struct spoolss_DriverFileInfo *info = NULL;
5457         uint32_t count = 0;
5458         WERROR result;
5459         uint32_t i;
5460
5461         *info_p = NULL;
5462         *count_p = 0;
5463
5464         if (strlen(driver->driver_path)) {
5465                 info = talloc_realloc(mem_ctx, info,
5466                                             struct spoolss_DriverFileInfo,
5467                                             count + 1);
5468                 W_ERROR_HAVE_NO_MEMORY(info);
5469                 result = fill_spoolss_DriverFileInfo(info,
5470                                                      &info[count],
5471                                                      cservername,
5472                                                      driver->driver_path,
5473                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5474                                                      0);
5475                 W_ERROR_NOT_OK_RETURN(result);
5476                 count++;
5477         }
5478
5479         if (strlen(driver->config_file)) {
5480                 info = talloc_realloc(mem_ctx, info,
5481                                             struct spoolss_DriverFileInfo,
5482                                             count + 1);
5483                 W_ERROR_HAVE_NO_MEMORY(info);
5484                 result = fill_spoolss_DriverFileInfo(info,
5485                                                      &info[count],
5486                                                      cservername,
5487                                                      driver->config_file,
5488                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5489                                                      0);
5490                 W_ERROR_NOT_OK_RETURN(result);
5491                 count++;
5492         }
5493
5494         if (strlen(driver->data_file)) {
5495                 info = talloc_realloc(mem_ctx, info,
5496                                             struct spoolss_DriverFileInfo,
5497                                             count + 1);
5498                 W_ERROR_HAVE_NO_MEMORY(info);
5499                 result = fill_spoolss_DriverFileInfo(info,
5500                                                      &info[count],
5501                                                      cservername,
5502                                                      driver->data_file,
5503                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5504                                                      0);
5505                 W_ERROR_NOT_OK_RETURN(result);
5506                 count++;
5507         }
5508
5509         if (strlen(driver->help_file)) {
5510                 info = talloc_realloc(mem_ctx, info,
5511                                             struct spoolss_DriverFileInfo,
5512                                             count + 1);
5513                 W_ERROR_HAVE_NO_MEMORY(info);
5514                 result = fill_spoolss_DriverFileInfo(info,
5515                                                      &info[count],
5516                                                      cservername,
5517                                                      driver->help_file,
5518                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5519                                                      0);
5520                 W_ERROR_NOT_OK_RETURN(result);
5521                 count++;
5522         }
5523
5524         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5525                 info = talloc_realloc(mem_ctx, info,
5526                                             struct spoolss_DriverFileInfo,
5527                                             count + 1);
5528                 W_ERROR_HAVE_NO_MEMORY(info);
5529                 result = fill_spoolss_DriverFileInfo(info,
5530                                                      &info[count],
5531                                                      cservername,
5532                                                      driver->dependent_files[i],
5533                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5534                                                      0);
5535                 W_ERROR_NOT_OK_RETURN(result);
5536                 count++;
5537         }
5538
5539         *info_p = info;
5540         *count_p = count;
5541
5542         return WERR_OK;
5543 }
5544
5545 /********************************************************************
5546  * fill a spoolss_DriverInfo101 struct
5547  ********************************************************************/
5548
5549 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5550                                           struct spoolss_DriverInfo101 *r,
5551                                           const struct spoolss_DriverInfo8 *driver,
5552                                           const char *servername)
5553 {
5554         const char *cservername = canon_servername(servername);
5555         WERROR result;
5556
5557         r->version              = driver->version;
5558
5559         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5560         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5561         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5562         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5563
5564         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5565                                                     cservername,
5566                                                     &r->file_info,
5567                                                     &r->file_count);
5568         if (!W_ERROR_IS_OK(result)) {
5569                 return result;
5570         }
5571
5572         FILL_DRIVER_STRING(mem_ctx,
5573                            driver->monitor_name,
5574                            r->monitor_name);
5575
5576         FILL_DRIVER_STRING(mem_ctx,
5577                            driver->default_datatype,
5578                            r->default_datatype);
5579
5580         result = string_array_from_driver_info(mem_ctx,
5581                                                driver->previous_names,
5582                                                &r->previous_names,
5583                                                NULL, NULL, 0);
5584         if (!W_ERROR_IS_OK(result)) {
5585                 return result;
5586         }
5587
5588         r->driver_date          = driver->driver_date;
5589         r->driver_version       = driver->driver_version;
5590
5591         FILL_DRIVER_STRING(mem_ctx,
5592                            driver->manufacturer_name,
5593                            r->manufacturer_name);
5594         FILL_DRIVER_STRING(mem_ctx,
5595                            driver->manufacturer_url,
5596                            r->manufacturer_url);
5597         FILL_DRIVER_STRING(mem_ctx,
5598                            driver->hardware_id,
5599                            r->hardware_id);
5600         FILL_DRIVER_STRING(mem_ctx,
5601                            driver->provider,
5602                            r->provider);
5603
5604         return WERR_OK;
5605 }
5606 #endif
5607 /********************************************************************
5608  ********************************************************************/
5609
5610 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5611                                                   const struct auth_session_info *session_info,
5612                                                   struct messaging_context *msg_ctx,
5613                                                   uint32_t level,
5614                                                   union spoolss_DriverInfo *r,
5615                                                   int snum,
5616                                                   const char *servername,
5617                                                   const char *architecture,
5618                                                   uint32_t version)
5619 {
5620         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5621         struct spoolss_DriverInfo8 *driver;
5622         WERROR result;
5623         struct dcerpc_binding_handle *b;
5624         TALLOC_CTX *tmp_ctx = NULL;
5625
5626         if (level == 101) {
5627                 return WERR_INVALID_LEVEL;
5628         }
5629
5630         tmp_ctx = talloc_new(mem_ctx);
5631         if (!tmp_ctx) {
5632                 return WERR_NOT_ENOUGH_MEMORY;
5633         }
5634
5635         result = winreg_printer_binding_handle(tmp_ctx,
5636                                                session_info,
5637                                                msg_ctx,
5638                                                &b);
5639         if (!W_ERROR_IS_OK(result)) {
5640                 goto done;
5641         }
5642
5643         result = winreg_get_printer(tmp_ctx, b,
5644                                     lp_const_servicename(snum),
5645                                     &pinfo2);
5646
5647         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5648                 win_errstr(result)));
5649
5650         if (!W_ERROR_IS_OK(result)) {
5651                 result = WERR_INVALID_PRINTER_NAME;
5652                 goto done;
5653         }
5654
5655         result = winreg_get_driver(tmp_ctx, b,
5656                                    architecture,
5657                                    pinfo2->drivername, version, &driver);
5658
5659         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5660                 win_errstr(result)));
5661
5662         if (!W_ERROR_IS_OK(result)) {
5663                 /*
5664                  * Is this a W2k client ?
5665                  */
5666
5667                 if (version < 3) {
5668                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5669                         goto done;
5670                 }
5671
5672                 /* Yes - try again with a WinNT driver. */
5673                 version = 2;
5674                 result = winreg_get_driver(tmp_ctx, b,
5675                                            architecture,
5676                                            pinfo2->drivername,
5677                                            version, &driver);
5678                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5679                         win_errstr(result)));
5680                 if (!W_ERROR_IS_OK(result)) {
5681                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5682                         goto done;
5683                 }
5684         }
5685
5686         /* these are allocated on mem_ctx and not tmp_ctx because they are
5687          * the 'return value' and need to utlive this call */
5688         switch (level) {
5689         case 1:
5690                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5691                 break;
5692         case 2:
5693                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5694                 break;
5695         case 3:
5696                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5697                 break;
5698         case 4:
5699                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5700                 break;
5701         case 5:
5702                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5703                 break;
5704         case 6:
5705                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5706                 break;
5707         case 8:
5708                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5709                 break;
5710 #if 0 /* disabled until marshalling issues are resolved - gd */
5711         case 101:
5712                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5713                 break;
5714 #endif
5715         default:
5716                 result = WERR_INVALID_LEVEL;
5717                 break;
5718         }
5719
5720 done:
5721         talloc_free(tmp_ctx);
5722         return result;
5723 }
5724
5725 /****************************************************************
5726  _spoolss_GetPrinterDriver2
5727 ****************************************************************/
5728
5729 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5730                                   struct spoolss_GetPrinterDriver2 *r)
5731 {
5732         struct printer_handle *printer;
5733         WERROR result;
5734         uint32_t version = r->in.client_major_version;
5735
5736         int snum;
5737
5738         /* that's an [in out] buffer */
5739
5740         if (!r->in.buffer && (r->in.offered != 0)) {
5741                 result = WERR_INVALID_PARAMETER;
5742                 goto err_info_free;
5743         }
5744
5745         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5746
5747         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5748                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5749                 result = WERR_INVALID_PRINTER_NAME;
5750                 goto err_info_free;
5751         }
5752
5753         *r->out.needed = 0;
5754         *r->out.server_major_version = 0;
5755         *r->out.server_minor_version = 0;
5756
5757         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5758                 result = WERR_INVALID_HANDLE;
5759                 goto err_info_free;
5760         }
5761
5762         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5763                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5764                         "downgrading to v3\n"));
5765                 version = SPOOLSS_DRIVER_VERSION_200X;
5766         }
5767
5768         result = construct_printer_driver_info_level(p->mem_ctx,
5769                                                      get_session_info_system(),
5770                                                      p->msg_ctx,
5771                                                      r->in.level, r->out.info,
5772                                                      snum, printer->servername,
5773                                                      r->in.architecture,
5774                                                      version);
5775         if (!W_ERROR_IS_OK(result)) {
5776                 goto err_info_free;
5777         }
5778
5779         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5780                                                r->out.info, r->in.level);
5781         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5782
5783         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5784
5785 err_info_free:
5786         TALLOC_FREE(r->out.info);
5787         return result;
5788 }
5789
5790
5791 /****************************************************************
5792  _spoolss_StartPagePrinter
5793 ****************************************************************/
5794
5795 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5796                                  struct spoolss_StartPagePrinter *r)
5797 {
5798         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5799
5800         if (!Printer) {
5801                 DEBUG(3,("_spoolss_StartPagePrinter: "
5802                         "Error in startpageprinter printer handle\n"));
5803                 return WERR_INVALID_HANDLE;
5804         }
5805
5806         Printer->page_started = true;
5807         return WERR_OK;
5808 }
5809
5810 /****************************************************************
5811  _spoolss_EndPagePrinter
5812 ****************************************************************/
5813
5814 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5815                                struct spoolss_EndPagePrinter *r)
5816 {
5817         int snum;
5818
5819         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5820
5821         if (!Printer) {
5822                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5823                         OUR_HANDLE(r->in.handle)));
5824                 return WERR_INVALID_HANDLE;
5825         }
5826
5827         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5828                 return WERR_INVALID_HANDLE;
5829
5830         Printer->page_started = false;
5831         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5832
5833         return WERR_OK;
5834 }
5835
5836 /****************************************************************
5837  _spoolss_StartDocPrinter
5838 ****************************************************************/
5839
5840 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5841                                 struct spoolss_StartDocPrinter *r)
5842 {
5843         struct spoolss_DocumentInfo1 *info_1;
5844         int snum;
5845         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5846         WERROR werr;
5847         char *rhost;
5848         int rc;
5849
5850         if (!Printer) {
5851                 DEBUG(2,("_spoolss_StartDocPrinter: "
5852                         "Invalid handle (%s:%u:%u)\n",
5853                         OUR_HANDLE(r->in.handle)));
5854                 return WERR_INVALID_HANDLE;
5855         }
5856
5857         if (Printer->jobid) {
5858                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5859                           "StartDocPrinter called twice! "
5860                           "(existing jobid = %d)\n", Printer->jobid));
5861                 return WERR_INVALID_HANDLE;
5862         }
5863
5864         if (r->in.info_ctr->level != 1) {
5865                 return WERR_INVALID_LEVEL;
5866         }
5867
5868         info_1 = r->in.info_ctr->info.info1;
5869
5870         /*
5871          * a nice thing with NT is it doesn't listen to what you tell it.
5872          * when asked to send _only_ RAW datas, it tries to send datas
5873          * in EMF format.
5874          *
5875          * So I add checks like in NT Server ...
5876          */
5877
5878         if (info_1->datatype) {
5879                 /*
5880                  * The v4 driver model used in Windows 8 declares print jobs
5881                  * intended to bypass the XPS processing layer by setting
5882                  * datatype to "XPS_PASS" instead of "RAW".
5883                  */
5884                 if ((strcmp(info_1->datatype, "RAW") != 0)
5885                  && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5886                         *r->out.job_id = 0;
5887                         return WERR_INVALID_DATATYPE;
5888                 }
5889         }
5890
5891         /* get the share number of the printer */
5892         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5893                 return WERR_INVALID_HANDLE;
5894         }
5895
5896         rc = get_remote_hostname(p->remote_address,
5897                                  &rhost,
5898                                  p->mem_ctx);
5899         if (rc < 0) {
5900                 return WERR_NOT_ENOUGH_MEMORY;
5901         }
5902         if (strequal(rhost,"UNKNOWN")) {
5903                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5904                                                          p->mem_ctx);
5905                 if (rhost == NULL) {
5906                         return WERR_NOT_ENOUGH_MEMORY;
5907                 }
5908         }
5909
5910         werr = print_job_start(p->session_info,
5911                                p->msg_ctx,
5912                                rhost,
5913                                snum,
5914                                info_1->document_name,
5915                                info_1->output_file,
5916                                Printer->devmode,
5917                                &Printer->jobid);
5918
5919         /* An error occured in print_job_start() so return an appropriate
5920            NT error code. */
5921
5922         if (!W_ERROR_IS_OK(werr)) {
5923                 return werr;
5924         }
5925
5926         Printer->document_started = true;
5927         *r->out.job_id = Printer->jobid;
5928
5929         return WERR_OK;
5930 }
5931
5932 /****************************************************************
5933  _spoolss_EndDocPrinter
5934 ****************************************************************/
5935
5936 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5937                               struct spoolss_EndDocPrinter *r)
5938 {
5939         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5940         NTSTATUS status;
5941         int snum;
5942
5943         if (!Printer) {
5944                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5945                         OUR_HANDLE(r->in.handle)));
5946                 return WERR_INVALID_HANDLE;
5947         }
5948
5949         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5950                 return WERR_INVALID_HANDLE;
5951         }
5952
5953         Printer->document_started = false;
5954         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5955         if (!NT_STATUS_IS_OK(status)) {
5956                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5957                           "print_job_end failed [%s]\n",
5958                           nt_errstr(status)));
5959         }
5960
5961         Printer->jobid = 0;
5962         return ntstatus_to_werror(status);
5963 }
5964
5965 /****************************************************************
5966  _spoolss_WritePrinter
5967 ****************************************************************/
5968
5969 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5970                              struct spoolss_WritePrinter *r)
5971 {
5972         ssize_t buffer_written;
5973         int snum;
5974         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5975
5976         if (!Printer) {
5977                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5978                         OUR_HANDLE(r->in.handle)));
5979                 *r->out.num_written = r->in._data_size;
5980                 return WERR_INVALID_HANDLE;
5981         }
5982
5983         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5984                 return WERR_INVALID_HANDLE;
5985
5986         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5987         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5988                                                    snum, Printer->jobid,
5989                                                    (const char *)r->in.data.data,
5990                                                    (size_t)r->in._data_size);
5991         if (buffer_written == (ssize_t)-1) {
5992                 *r->out.num_written = 0;
5993                 if (errno == ENOSPC)
5994                         return WERR_NO_SPOOL_SPACE;
5995                 else
5996                         return WERR_ACCESS_DENIED;
5997         }
5998
5999         *r->out.num_written = r->in._data_size;
6000
6001         return WERR_OK;
6002 }
6003
6004 /********************************************************************
6005  * api_spoolss_getprinter
6006  * called from the spoolss dispatcher
6007  *
6008  ********************************************************************/
6009
6010 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
6011                               struct pipes_struct *p)
6012 {
6013         const struct auth_session_info *session_info = p->session_info;
6014         int snum;
6015         WERROR errcode = WERR_INVALID_FUNCTION;
6016         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6017
6018         if (!Printer) {
6019                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
6020                         OUR_HANDLE(handle)));
6021                 return WERR_INVALID_HANDLE;
6022         }
6023
6024         if (!get_printer_snum(p, handle, &snum, NULL))
6025                 return WERR_INVALID_HANDLE;
6026
6027         switch (command) {
6028         case SPOOLSS_PRINTER_CONTROL_PAUSE:
6029                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
6030                 break;
6031         case SPOOLSS_PRINTER_CONTROL_RESUME:
6032         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6033                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6034                 break;
6035         case SPOOLSS_PRINTER_CONTROL_PURGE:
6036                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6037                 break;
6038         default:
6039                 return WERR_INVALID_LEVEL;
6040         }
6041
6042         return errcode;
6043 }
6044
6045
6046 /****************************************************************
6047  _spoolss_AbortPrinter
6048  * From MSDN: "Deletes printer's spool file if printer is configured
6049  * for spooling"
6050 ****************************************************************/
6051
6052 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6053                              struct spoolss_AbortPrinter *r)
6054 {
6055         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
6056         int             snum;
6057         WERROR          errcode = WERR_OK;
6058
6059         if (!Printer) {
6060                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6061                         OUR_HANDLE(r->in.handle)));
6062                 return WERR_INVALID_HANDLE;
6063         }
6064
6065         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6066                 return WERR_INVALID_HANDLE;
6067
6068         if (!Printer->document_started) {
6069                 return WERR_SPL_NO_STARTDOC;
6070         }
6071
6072         errcode = print_job_delete(p->session_info,
6073                                    p->msg_ctx,
6074                                    snum,
6075                                    Printer->jobid);
6076
6077         return errcode;
6078 }
6079
6080 /********************************************************************
6081  * called by spoolss_api_setprinter
6082  * when updating a printer description
6083  ********************************************************************/
6084
6085 static WERROR update_printer_sec(struct policy_handle *handle,
6086                                  struct pipes_struct *p,
6087                                  struct sec_desc_buf *secdesc_ctr)
6088 {
6089         struct spoolss_security_descriptor *new_secdesc = NULL;
6090         struct spoolss_security_descriptor *old_secdesc = NULL;
6091         const char *printer = NULL;
6092         WERROR result;
6093         int snum = -1;
6094         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6095         struct dcerpc_binding_handle *b;
6096         TALLOC_CTX *tmp_ctx = NULL;
6097         bool ok = false;
6098
6099         if (!Printer) {
6100                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6101                          OUR_HANDLE(handle)));
6102
6103                 result = WERR_INVALID_HANDLE;
6104                 goto done;
6105         }
6106
6107         if (secdesc_ctr == NULL) {
6108                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6109                 result = WERR_INVALID_PARAMETER;
6110                 goto done;
6111         }
6112
6113         switch (Printer->printer_type) {
6114         case SPLHND_SERVER:
6115                 break;
6116         case SPLHND_PRINTER:
6117                 if (!get_printer_snum(p, handle, &snum, NULL)) {
6118                         DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6119                                  OUR_HANDLE(handle)));
6120                         result = WERR_INVALID_HANDLE;
6121                         goto done;
6122                 }
6123                 printer = lp_const_servicename(snum);
6124                 break;
6125         default:
6126                 break;
6127         }
6128
6129         /* Check the user has permissions to change the security
6130            descriptor.  By experimentation with two NT machines, the user
6131            requires Full Access to the printer to change security
6132            information. */
6133
6134         switch (Printer->printer_type) {
6135         case SPLHND_SERVER:
6136                 ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
6137                 break;
6138         case SPLHND_PRINTER:
6139                 ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
6140                 break;
6141         default:
6142                 break;
6143         }
6144
6145         if (!ok) {
6146                 DEBUG(4,("update_printer_sec: updated denied by printer permissions "
6147                         "(access_granted: 0x%08x)\n", Printer->access_granted));
6148                 result = WERR_ACCESS_DENIED;
6149                 goto done;
6150         }
6151
6152         tmp_ctx = talloc_new(p->mem_ctx);
6153         if (!tmp_ctx) {
6154                 return WERR_NOT_ENOUGH_MEMORY;
6155         }
6156
6157         result = winreg_printer_binding_handle(tmp_ctx,
6158                                                get_session_info_system(),
6159                                                p->msg_ctx,
6160                                                &b);
6161         if (!W_ERROR_IS_OK(result)) {
6162                 goto done;
6163         }
6164
6165         /* NT seems to like setting the security descriptor even though
6166            nothing may have actually changed. */
6167
6168         if (printer != NULL) {
6169                 result = winreg_get_printer_secdesc(tmp_ctx, b,
6170                                                     printer,
6171                                                     &old_secdesc);
6172         } else {
6173                 result = winreg_get_printserver_secdesc(tmp_ctx, b,
6174                                                         &old_secdesc);
6175         }
6176         if (!W_ERROR_IS_OK(result)) {
6177                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6178                 result = WERR_INVALID_HANDLE;
6179                 goto done;
6180         }
6181
6182         if (DEBUGLEVEL >= 10) {
6183                 struct security_acl *the_acl;
6184                 int i;
6185
6186                 the_acl = old_secdesc->dacl;
6187                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6188                            printer, the_acl->num_aces));
6189
6190                 for (i = 0; i < the_acl->num_aces; i++) {
6191                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6192                                            &the_acl->aces[i].trustee),
6193                                   the_acl->aces[i].access_mask));
6194                 }
6195
6196                 the_acl = secdesc_ctr->sd->dacl;
6197
6198                 if (the_acl) {
6199                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6200                                    printer, the_acl->num_aces));
6201
6202                         for (i = 0; i < the_acl->num_aces; i++) {
6203                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6204                                                    &the_acl->aces[i].trustee),
6205                                            the_acl->aces[i].access_mask));
6206                         }
6207                 } else {
6208                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6209                 }
6210         }
6211
6212         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6213         if (new_secdesc == NULL) {
6214                 result = WERR_NOT_ENOUGH_MEMORY;
6215                 goto done;
6216         }
6217
6218         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6219                 result = WERR_OK;
6220                 goto done;
6221         }
6222
6223         if (printer != NULL) {
6224                 result = winreg_set_printer_secdesc(tmp_ctx, b,
6225                                                     printer,
6226                                                     new_secdesc);
6227         } else {
6228                 result = winreg_set_printserver_secdesc(tmp_ctx, b,
6229                                                         new_secdesc);
6230         }
6231
6232 done:
6233         talloc_free(tmp_ctx);
6234         return result;
6235 }
6236
6237 /********************************************************************
6238  Canonicalize printer info from a client
6239  ********************************************************************/
6240
6241 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6242                              struct spoolss_SetPrinterInfo2 *info2,
6243                              int snum)
6244 {
6245         fstring printername;
6246         const char *p;
6247
6248         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6249                 "portname=%s drivername=%s comment=%s location=%s\n",
6250                 info2->servername, info2->printername, info2->sharename,
6251                 info2->portname, info2->drivername, info2->comment,
6252                 info2->location));
6253
6254         /* we force some elements to "correct" values */
6255         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6256         if (info2->servername == NULL) {
6257                 return false;
6258         }
6259         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6260         if (info2->sharename == NULL) {
6261                 return false;
6262         }
6263
6264         /* check to see if we allow printername != sharename */
6265         if (lp_force_printername(snum)) {
6266                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6267                                         lp_netbios_name(), info2->sharename);
6268         } else {
6269                 /* make sure printername is in \\server\printername format */
6270                 fstrcpy(printername, info2->printername);
6271                 p = printername;
6272                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6273                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6274                                 p++;
6275                 }
6276
6277                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6278                                         lp_netbios_name(), p);
6279         }
6280         if (info2->printername == NULL) {
6281                 return false;
6282         }
6283
6284         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6285         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6286
6287         return true;
6288 }
6289
6290 /****************************************************************************
6291 ****************************************************************************/
6292
6293 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6294 {
6295         char *cmd = lp_addport_command(talloc_tos());
6296         char *command = NULL;
6297         int ret;
6298         bool is_print_op = false;
6299
6300         if ( !*cmd ) {
6301                 return WERR_ACCESS_DENIED;
6302         }
6303
6304         command = talloc_asprintf(ctx,
6305                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6306         if (!command) {
6307                 return WERR_NOT_ENOUGH_MEMORY;
6308         }
6309
6310         if ( token )
6311                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6312
6313         DEBUG(10,("Running [%s]\n", command));
6314
6315         /********* BEGIN SePrintOperatorPrivilege **********/
6316
6317         if ( is_print_op )
6318                 become_root();
6319
6320         ret = smbrun(command, NULL);
6321
6322         if ( is_print_op )
6323                 unbecome_root();
6324
6325         /********* END SePrintOperatorPrivilege **********/
6326
6327         DEBUGADD(10,("returned [%d]\n", ret));
6328
6329         TALLOC_FREE(command);
6330
6331         if ( ret != 0 ) {
6332                 return WERR_ACCESS_DENIED;
6333         }
6334
6335         return WERR_OK;
6336 }
6337
6338 /****************************************************************************
6339 ****************************************************************************/
6340
6341 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6342                                    int snum)
6343 {
6344         /*
6345          * As we do not know if we are embedded in the file server process
6346          * or not, we have to pretend that all shares are in use.
6347          */
6348         return true;
6349 }
6350
6351 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6352                              struct spoolss_SetPrinterInfo2 *info2,
6353                              const char *remote_machine,
6354                              struct messaging_context *msg_ctx)
6355 {
6356         char *cmd = lp_addprinter_command(talloc_tos());
6357         char **qlines;
6358         char *command = NULL;
6359         int numlines;
6360         int ret;
6361         int fd;
6362         bool is_print_op = false;
6363
6364         if (!remote_machine) {
6365                 return false;
6366         }
6367
6368         command = talloc_asprintf(ctx,
6369                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6370                         cmd, info2->printername, info2->sharename,
6371                         info2->portname, info2->drivername,
6372                         info2->location, info2->comment, remote_machine);
6373         if (!command) {
6374                 return false;
6375         }
6376
6377         if ( token )
6378                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6379
6380         DEBUG(10,("Running [%s]\n", command));
6381
6382         /********* BEGIN SePrintOperatorPrivilege **********/
6383
6384         if ( is_print_op )
6385                 become_root();
6386
6387         if ( (ret = smbrun(command, &fd)) == 0 ) {
6388                 /* Tell everyone we updated smb.conf. */
6389                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6390         }
6391
6392         if ( is_print_op )
6393                 unbecome_root();
6394
6395         /********* END SePrintOperatorPrivilege **********/
6396
6397         DEBUGADD(10,("returned [%d]\n", ret));
6398
6399         TALLOC_FREE(command);
6400
6401         if ( ret != 0 ) {
6402                 if (fd != -1)
6403                         close(fd);
6404                 return false;
6405         }
6406
6407         /* reload our services immediately */
6408         become_root();
6409         reload_services(NULL, spoolss_conn_snum_used, false);
6410         unbecome_root();
6411
6412         numlines = 0;
6413         /* Get lines and convert them back to dos-codepage */
6414         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6415         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6416         close(fd);
6417
6418         /* Set the portname to what the script says the portname should be. */
6419         /* but don't require anything to be return from the script exit a good error code */
6420
6421         if (numlines) {
6422                 /* Set the portname to what the script says the portname should be. */
6423                 info2->portname = talloc_strdup(ctx, qlines[0]);
6424                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6425         }
6426
6427         TALLOC_FREE(qlines);
6428         return true;
6429 }
6430
6431 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6432                                const struct auth_session_info *session_info,
6433                                struct messaging_context *msg_ctx,
6434                                int snum,
6435                                struct spoolss_SetPrinterInfo2 *printer,
6436                                struct spoolss_PrinterInfo2 *old_printer)
6437 {
6438         bool force_update = (old_printer == NULL);
6439         const char *dnsdomname;
6440         const char *longname;
6441         const char *uncname;
6442         const char *spooling;
6443         DATA_BLOB buffer;
6444         WERROR result = WERR_OK;
6445         struct dcerpc_binding_handle *b;
6446         TALLOC_CTX *tmp_ctx;
6447         bool ok;
6448
6449         tmp_ctx = talloc_new(mem_ctx);
6450         if (!tmp_ctx) {
6451                 return WERR_NOT_ENOUGH_MEMORY;
6452         }
6453
6454         result = winreg_printer_binding_handle(tmp_ctx,
6455                                                session_info,
6456                                                msg_ctx,
6457                                                &b);
6458         if (!W_ERROR_IS_OK(result)) {
6459                 goto done;
6460         }
6461
6462         if (printer->drivername != NULL &&
6463             (force_update ||
6464              !strequal(printer->drivername, old_printer->drivername))) {
6465                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6466                 if (!ok) {
6467                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6468                         result = WERR_INVALID_DATA;
6469                         goto done;
6470                 }
6471                 result = winreg_set_printer_dataex(tmp_ctx, b,
6472                                           printer->sharename,
6473                                           SPOOL_DSSPOOLER_KEY,
6474                                           SPOOL_REG_DRIVERNAME,
6475                                           REG_SZ,
6476                                           buffer.data,
6477                                           buffer.length);
6478                 if (!W_ERROR_IS_OK(result)) {
6479                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6480                         goto done;
6481                 }
6482
6483                 if (!force_update) {
6484                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6485                                 printer->drivername));
6486
6487                         notify_printer_driver(server_event_context(), msg_ctx,
6488                                               snum, printer->drivername ?
6489                                               printer->drivername : "");
6490                 }
6491         }
6492
6493         if (printer->comment != NULL &&
6494             (force_update ||
6495              !strequal(printer->comment, old_printer->comment))) {
6496                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6497                 if (!ok) {
6498                         DEBUG(0, ("comment data corrupted\n"));
6499                         result = WERR_INVALID_DATA;
6500                         goto done;
6501                 }
6502                 result = winreg_set_printer_dataex(tmp_ctx, b,
6503                                           printer->sharename,
6504                                           SPOOL_DSSPOOLER_KEY,
6505                                           SPOOL_REG_DESCRIPTION,
6506                                           REG_SZ,
6507                                           buffer.data,
6508                                           buffer.length);
6509                 if (!W_ERROR_IS_OK(result)) {
6510                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6511                         goto done;
6512                 }
6513
6514                 if (!force_update) {
6515                         notify_printer_comment(server_event_context(), msg_ctx,
6516                                                snum, printer->comment ?
6517                                                printer->comment : "");
6518                 }
6519         }
6520
6521         if (printer->sharename != NULL &&
6522             (force_update ||
6523              !strequal(printer->sharename, old_printer->sharename))) {
6524                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6525                 if (!ok) {
6526                         DEBUG(0, ("sharename data corrupted\n"));
6527                         result = WERR_INVALID_DATA;
6528                         goto done;
6529                 }
6530                 result = winreg_set_printer_dataex(tmp_ctx, b,
6531                                           printer->sharename,
6532                                           SPOOL_DSSPOOLER_KEY,
6533                                           SPOOL_REG_PRINTSHARENAME,
6534                                           REG_SZ,
6535                                           buffer.data,
6536                                           buffer.length);
6537                 if (!W_ERROR_IS_OK(result)) {
6538                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6539                         goto done;
6540                 }
6541
6542                 if (!force_update) {
6543                         notify_printer_sharename(server_event_context(),
6544                                                  msg_ctx,
6545                                                  snum, printer->sharename ?
6546                                                  printer->sharename : "");
6547                 }
6548
6549                 /* name change, purge any cache entries for the old */
6550                 prune_printername_cache();
6551         }
6552
6553         if (printer->printername != NULL &&
6554             (force_update ||
6555              !strequal(printer->printername, old_printer->printername))) {
6556                 const char *p;
6557
6558                 p = strrchr(printer->printername, '\\' );
6559                 if (p != NULL) {
6560                         p++;
6561                 } else {
6562                         p = printer->printername;
6563                 }
6564
6565                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6566                 if (!ok) {
6567                         DEBUG(0, ("printername data corrupted\n"));
6568                         result = WERR_INVALID_DATA;
6569                         goto done;
6570                 }
6571                 result = winreg_set_printer_dataex(tmp_ctx, b,
6572                                           printer->sharename,
6573                                           SPOOL_DSSPOOLER_KEY,
6574                                           SPOOL_REG_PRINTERNAME,
6575                                           REG_SZ,
6576                                           buffer.data,
6577                                           buffer.length);
6578                 if (!W_ERROR_IS_OK(result)) {
6579                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6580                         goto done;
6581                 }
6582
6583                 if (!force_update) {
6584                         notify_printer_printername(server_event_context(),
6585                                                    msg_ctx, snum, p ? p : "");
6586                 }
6587
6588                 /* name change, purge any cache entries for the old */
6589                 prune_printername_cache();
6590         }
6591
6592         if (printer->portname != NULL &&
6593             (force_update ||
6594              !strequal(printer->portname, old_printer->portname))) {
6595                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6596                 if (!ok) {
6597                         DEBUG(0, ("portname data corrupted\n"));
6598                         result = WERR_INVALID_DATA;
6599                         goto done;
6600                 }
6601                 result = winreg_set_printer_dataex(tmp_ctx, b,
6602                                           printer->sharename,
6603                                           SPOOL_DSSPOOLER_KEY,
6604                                           SPOOL_REG_PORTNAME,
6605                                           REG_SZ,
6606                                           buffer.data,
6607                                           buffer.length);
6608                 if (!W_ERROR_IS_OK(result)) {
6609                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6610                         goto done;
6611                 }
6612
6613                 if (!force_update) {
6614                         notify_printer_port(server_event_context(),
6615                                             msg_ctx, snum, printer->portname ?
6616                                             printer->portname : "");
6617                 }
6618         }
6619
6620         if (printer->location != NULL &&
6621             (force_update ||
6622              !strequal(printer->location, old_printer->location))) {
6623                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6624                 if (!ok) {
6625                         DEBUG(0, ("location data corrupted\n"));
6626                         result = WERR_INVALID_DATA;
6627                         goto done;
6628                 }
6629                 result = winreg_set_printer_dataex(tmp_ctx, b,
6630                                           printer->sharename,
6631                                           SPOOL_DSSPOOLER_KEY,
6632                                           SPOOL_REG_LOCATION,
6633                                           REG_SZ,
6634                                           buffer.data,
6635                                           buffer.length);
6636                 if (!W_ERROR_IS_OK(result)) {
6637                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6638                         goto done;
6639                 }
6640
6641                 if (!force_update) {
6642                         notify_printer_location(server_event_context(),
6643                                                 msg_ctx, snum,
6644                                                 printer->location ?
6645                                                 printer->location : "");
6646                 }
6647         }
6648
6649         if (printer->sepfile != NULL &&
6650             (force_update ||
6651              !strequal(printer->sepfile, old_printer->sepfile))) {
6652                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6653                 if (!ok) {
6654                         DEBUG(0, ("sepfile data corrupted\n"));
6655                         result = WERR_INVALID_DATA;
6656                         goto done;
6657                 }
6658                 result = winreg_set_printer_dataex(tmp_ctx, b,
6659                                           printer->sharename,
6660                                           SPOOL_DSSPOOLER_KEY,
6661                                           SPOOL_REG_PRINTSEPARATORFILE,
6662                                           REG_SZ,
6663                                           buffer.data,
6664                                           buffer.length);
6665                 if (!W_ERROR_IS_OK(result)) {
6666                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6667                         goto done;
6668                 }
6669
6670                 if (!force_update) {
6671                         notify_printer_sepfile(server_event_context(),
6672                                                msg_ctx, snum,
6673                                                printer->sepfile ?
6674                                                printer->sepfile : "");
6675                 }
6676         }
6677
6678         if (printer->starttime != 0 &&
6679             (force_update ||
6680              printer->starttime != old_printer->starttime)) {
6681                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6682                 SIVAL(buffer.data, 0, printer->starttime);
6683                 result = winreg_set_printer_dataex(tmp_ctx, b,
6684                                           printer->sharename,
6685                                           SPOOL_DSSPOOLER_KEY,
6686                                           SPOOL_REG_PRINTSTARTTIME,
6687                                           REG_DWORD,
6688                                           buffer.data,
6689                                           buffer.length);
6690                 if (!W_ERROR_IS_OK(result)) {
6691                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6692                         goto done;
6693                 }
6694         }
6695
6696         if (printer->untiltime != 0 &&
6697             (force_update ||
6698              printer->untiltime != old_printer->untiltime)) {
6699                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6700                 SIVAL(buffer.data, 0, printer->untiltime);
6701                 result = winreg_set_printer_dataex(tmp_ctx, b,
6702                                           printer->sharename,
6703                                           SPOOL_DSSPOOLER_KEY,
6704                                           SPOOL_REG_PRINTENDTIME,
6705                                           REG_DWORD,
6706                                           buffer.data,
6707                                           buffer.length);
6708                 if (!W_ERROR_IS_OK(result)) {
6709                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6710                         goto done;
6711                 }
6712         }
6713
6714         if (force_update || printer->priority != old_printer->priority) {
6715                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6716                 SIVAL(buffer.data, 0, printer->priority);
6717                 result = winreg_set_printer_dataex(tmp_ctx, b,
6718                                           printer->sharename,
6719                                           SPOOL_DSSPOOLER_KEY,
6720                                           SPOOL_REG_PRIORITY,
6721                                           REG_DWORD,
6722                                           buffer.data,
6723                                           buffer.length);
6724                 if (!W_ERROR_IS_OK(result)) {
6725                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6726                         goto done;
6727                 }
6728         }
6729
6730         if (force_update || printer->attributes != old_printer->attributes) {
6731                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6732                 SIVAL(buffer.data, 0, (printer->attributes &
6733                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6734                 result = winreg_set_printer_dataex(tmp_ctx, b,
6735                                           printer->sharename,
6736                                           SPOOL_DSSPOOLER_KEY,
6737                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6738                                           REG_DWORD,
6739                                           buffer.data,
6740                                           buffer.length);
6741                 if (!W_ERROR_IS_OK(result)) {
6742                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6743                         goto done;
6744                 }
6745
6746                 switch (printer->attributes & 0x3) {
6747                         case 0:
6748                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6749                                 break;
6750                         case 1:
6751                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6752                                 break;
6753                         case 2:
6754                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6755                                 break;
6756                         default:
6757                                 spooling = "unknown";
6758                 }
6759                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6760                 if (!ok) {
6761                         DEBUG(0, ("printSpooling data corrupted\n"));
6762                         result = WERR_INVALID_DATA;
6763                         goto done;
6764                 }
6765                 winreg_set_printer_dataex(tmp_ctx, b,
6766                                           printer->sharename,
6767                                           SPOOL_DSSPOOLER_KEY,
6768                                           SPOOL_REG_PRINTSPOOLING,
6769                                           REG_SZ,
6770                                           buffer.data,
6771                                           buffer.length);
6772         }
6773
6774         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6775         if (!ok) {
6776                 DEBUG(0, ("shortServerName data corrupted\n"));
6777                 result = WERR_INVALID_DATA;
6778                 goto done;
6779         }
6780         result = winreg_set_printer_dataex(tmp_ctx, b,
6781                                   printer->sharename,
6782                                   SPOOL_DSSPOOLER_KEY,
6783                                   SPOOL_REG_SHORTSERVERNAME,
6784                                   REG_SZ,
6785                                   buffer.data,
6786                                   buffer.length);
6787         if (!W_ERROR_IS_OK(result)) {
6788                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6789                 goto done;
6790         }
6791
6792         dnsdomname = get_mydnsfullname();
6793         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6794                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6795         } else {
6796                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6797         }
6798         if (longname == NULL) {
6799                 result = WERR_NOT_ENOUGH_MEMORY;
6800                 goto done;
6801         }
6802
6803         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6804         if (!ok) {
6805                 DEBUG(0, ("longname data corrupted\n"));
6806                 result = WERR_INVALID_DATA;
6807                 goto done;
6808         }
6809         result = winreg_set_printer_dataex(tmp_ctx, b,
6810                                            printer->sharename,
6811                                            SPOOL_DSSPOOLER_KEY,
6812                                            SPOOL_REG_SERVERNAME,
6813                                            REG_SZ,
6814                                            buffer.data,
6815                                            buffer.length);
6816         if (!W_ERROR_IS_OK(result)) {
6817                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6818                 goto done;
6819         }
6820
6821         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6822                                   lp_netbios_name(), printer->sharename);
6823         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6824         if (!ok) {
6825                 DEBUG(0, ("uncName data corrupted\n"));
6826                 result = WERR_INVALID_DATA;
6827                 goto done;
6828         }
6829         result = winreg_set_printer_dataex(tmp_ctx, b,
6830                                   printer->sharename,
6831                                   SPOOL_DSSPOOLER_KEY,
6832                                   SPOOL_REG_UNCNAME,
6833                                   REG_SZ,
6834                                   buffer.data,
6835                                   buffer.length);
6836         if (!W_ERROR_IS_OK(result)) {
6837                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6838                 goto done;
6839         }
6840
6841 done:
6842         talloc_free(tmp_ctx);
6843         return result;
6844 }
6845
6846 /********************************************************************
6847  * Called by spoolss_api_setprinter
6848  * when updating a printer description.
6849  ********************************************************************/
6850
6851 static WERROR update_printer(struct pipes_struct *p,
6852                              struct policy_handle *handle,
6853                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6854                              struct spoolss_DeviceMode *devmode)
6855 {
6856         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6857         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6858         struct spoolss_PrinterInfo2 *old_printer;
6859         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6860         int snum;
6861         WERROR result = WERR_OK;
6862         TALLOC_CTX *tmp_ctx;
6863         struct dcerpc_binding_handle *b;
6864
6865         DEBUG(8,("update_printer\n"));
6866
6867         tmp_ctx = talloc_new(p->mem_ctx);
6868         if (tmp_ctx == NULL) {
6869                 return WERR_NOT_ENOUGH_MEMORY;
6870         }
6871
6872         if (!Printer) {
6873                 result = WERR_INVALID_HANDLE;
6874                 goto done;
6875         }
6876
6877         if (!get_printer_snum(p, handle, &snum, NULL)) {
6878                 result = WERR_INVALID_HANDLE;
6879                 goto done;
6880         }
6881
6882         result = winreg_printer_binding_handle(tmp_ctx,
6883                                                get_session_info_system(),
6884                                                p->msg_ctx,
6885                                                &b);
6886         if (!W_ERROR_IS_OK(result)) {
6887                 goto done;
6888         }
6889
6890         result = winreg_get_printer(tmp_ctx, b,
6891                                     lp_const_servicename(snum),
6892                                     &old_printer);
6893         if (!W_ERROR_IS_OK(result)) {
6894                 result = WERR_INVALID_HANDLE;
6895                 goto done;
6896         }
6897
6898         /* Do sanity check on the requested changes for Samba */
6899         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6900                 result = WERR_INVALID_PARAMETER;
6901                 goto done;
6902         }
6903
6904         /* FIXME!!! If the driver has changed we really should verify that
6905            it is installed before doing much else   --jerry */
6906
6907         /* Check calling user has permission to update printer description */
6908         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6909                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6910                 result = WERR_ACCESS_DENIED;
6911                 goto done;
6912         }
6913
6914         /* Call addprinter hook */
6915         /* Check changes to see if this is really needed */
6916
6917         if (*lp_addprinter_command(talloc_tos()) &&
6918                         (!strequal(printer->drivername, old_printer->drivername) ||
6919                          !strequal(printer->comment, old_printer->comment) ||
6920                          !strequal(printer->portname, old_printer->portname) ||
6921                          !strequal(printer->location, old_printer->location)) )
6922         {
6923                 char *raddr;
6924
6925                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6926                                                          p->mem_ctx);
6927                 if (raddr == NULL) {
6928                         return WERR_NOT_ENOUGH_MEMORY;
6929                 }
6930
6931                 /* add_printer_hook() will call reload_services() */
6932                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6933                                       printer, raddr,
6934                                       p->msg_ctx)) {
6935                         result = WERR_ACCESS_DENIED;
6936                         goto done;
6937                 }
6938         }
6939
6940         result = update_dsspooler(tmp_ctx,
6941                                   get_session_info_system(),
6942                                   p->msg_ctx,
6943                                   snum,
6944                                   printer,
6945                                   old_printer);
6946         if (!W_ERROR_IS_OK(result)) {
6947                 goto done;
6948         }
6949
6950         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6951
6952         if (devmode == NULL) {
6953                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6954         }
6955         result = winreg_update_printer(tmp_ctx, b,
6956                                        printer->sharename,
6957                                        printer_mask,
6958                                        printer,
6959                                        devmode,
6960                                        NULL);
6961
6962 done:
6963         talloc_free(tmp_ctx);
6964
6965         return result;
6966 }
6967
6968 /****************************************************************************
6969 ****************************************************************************/
6970 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6971                                            struct policy_handle *handle,
6972                                            struct spoolss_SetPrinterInfo7 *info7)
6973 {
6974 #ifdef HAVE_ADS
6975         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6976         WERROR result;
6977         int snum;
6978         struct printer_handle *Printer;
6979
6980         if ( lp_security() != SEC_ADS ) {
6981                 return WERR_INVALID_LEVEL;
6982         }
6983
6984         Printer = find_printer_index_by_hnd(p, handle);
6985
6986         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6987
6988         if (!Printer)
6989                 return WERR_INVALID_HANDLE;
6990
6991         if (!get_printer_snum(p, handle, &snum, NULL))
6992                 return WERR_INVALID_HANDLE;
6993
6994         result = winreg_get_printer_internal(p->mem_ctx,
6995                                     get_session_info_system(),
6996                                     p->msg_ctx,
6997                                     lp_servicename(talloc_tos(), snum),
6998                                     &pinfo2);
6999         if (!W_ERROR_IS_OK(result)) {
7000                 return WERR_INVALID_HANDLE;
7001         }
7002
7003         nt_printer_publish(pinfo2,
7004                            get_session_info_system(),
7005                            p->msg_ctx,
7006                            pinfo2,
7007                            info7->action);
7008
7009         TALLOC_FREE(pinfo2);
7010         return WERR_OK;
7011 #else
7012         return WERR_INVALID_LEVEL;
7013 #endif
7014 }
7015
7016 /********************************************************************
7017  ********************************************************************/
7018
7019 static WERROR update_printer_devmode(struct pipes_struct *p,
7020                                      struct policy_handle *handle,
7021                                      struct spoolss_DeviceMode *devmode)
7022 {
7023         int snum;
7024         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7025         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
7026
7027         DEBUG(8,("update_printer_devmode\n"));
7028
7029         if (!Printer) {
7030                 return WERR_INVALID_HANDLE;
7031         }
7032
7033         if (!get_printer_snum(p, handle, &snum, NULL)) {
7034                 return WERR_INVALID_HANDLE;
7035         }
7036
7037         /* Check calling user has permission to update printer description */
7038         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7039                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7040                 return WERR_ACCESS_DENIED;
7041         }
7042
7043         return winreg_update_printer_internal(p->mem_ctx,
7044                                      get_session_info_system(),
7045                                      p->msg_ctx,
7046                                      lp_const_servicename(snum),
7047                                      info2_mask,
7048                                      NULL,
7049                                      devmode,
7050                                      NULL);
7051 }
7052
7053
7054 /****************************************************************
7055  _spoolss_SetPrinter
7056 ****************************************************************/
7057
7058 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
7059                            struct spoolss_SetPrinter *r)
7060 {
7061         WERROR result;
7062
7063         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7064
7065         if (!Printer) {
7066                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
7067                         OUR_HANDLE(r->in.handle)));
7068                 return WERR_INVALID_HANDLE;
7069         }
7070
7071         /* check the level */
7072         switch (r->in.info_ctr->level) {
7073                 case 0:
7074                         return control_printer(r->in.handle, r->in.command, p);
7075                 case 2:
7076                         result = update_printer(p, r->in.handle,
7077                                                 r->in.info_ctr,
7078                                                 r->in.devmode_ctr->devmode);
7079                         if (!W_ERROR_IS_OK(result))
7080                                 return result;
7081                         if (r->in.secdesc_ctr->sd)
7082                                 result = update_printer_sec(r->in.handle, p,
7083                                                             r->in.secdesc_ctr);
7084                         return result;
7085                 case 3:
7086                         return update_printer_sec(r->in.handle, p,
7087                                                   r->in.secdesc_ctr);
7088                 case 4: {
7089                         struct spoolss_PrinterInfo2 *old_printer;
7090                         struct spoolss_SetPrinterInfo2 *set_old_printer;
7091                         struct spoolss_SetPrinterInfoCtr *info_ctr;
7092                         struct dcerpc_binding_handle *b;
7093                         int snum;
7094                         TALLOC_CTX *tmp_ctx;
7095
7096                         tmp_ctx = talloc_new(p->mem_ctx);
7097                         if (tmp_ctx == NULL) {
7098                                 return WERR_NOT_ENOUGH_MEMORY;
7099                         }
7100
7101                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7102                                 TALLOC_FREE(tmp_ctx);
7103                                 return WERR_INVALID_HANDLE;
7104                         }
7105
7106                         result = winreg_printer_binding_handle(tmp_ctx,
7107                                                                get_session_info_system(),
7108                                                                p->msg_ctx,
7109                                                                &b);
7110                         if (!W_ERROR_IS_OK(result)) {
7111                                 TALLOC_FREE(tmp_ctx);
7112                                 return result;
7113                         }
7114
7115                         result = winreg_get_printer(tmp_ctx, b,
7116                                                     lp_const_servicename(snum),
7117                                                     &old_printer);
7118                         if (!W_ERROR_IS_OK(result)) {
7119                                 TALLOC_FREE(tmp_ctx);
7120                                 return WERR_INVALID_HANDLE;
7121                         }
7122
7123                         old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
7124                         if (old_printer->servername == NULL) {
7125                                 TALLOC_FREE(tmp_ctx);
7126                                 return WERR_NOT_ENOUGH_MEMORY;
7127                         }
7128
7129                         old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
7130                         if (old_printer->printername == NULL) {
7131                                 TALLOC_FREE(tmp_ctx);
7132                                 return WERR_NOT_ENOUGH_MEMORY;
7133                         }
7134
7135                         old_printer->attributes = r->in.info_ctr->info.info4->attributes;
7136
7137                         set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
7138                         if (set_old_printer == NULL) {
7139                                 TALLOC_FREE(tmp_ctx);
7140                                 return WERR_NOT_ENOUGH_MEMORY;
7141                         }
7142
7143                         spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
7144
7145                         info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
7146                         if (info_ctr == NULL) {
7147                                 TALLOC_FREE(tmp_ctx);
7148                                 return WERR_NOT_ENOUGH_MEMORY;
7149                         }
7150
7151                         info_ctr->level = 2;
7152                         info_ctr->info.info2 = set_old_printer;
7153
7154                         result = update_printer(p, r->in.handle,
7155                                                 info_ctr,
7156                                                 r->in.devmode_ctr->devmode);
7157
7158                         if (!W_ERROR_IS_OK(result)) {
7159                                 TALLOC_FREE(tmp_ctx);
7160                                 return result;
7161                         }
7162
7163                         if (r->in.secdesc_ctr->sd) {
7164                                 result = update_printer_sec(r->in.handle, p,
7165                                                             r->in.secdesc_ctr);
7166                         }
7167
7168                         TALLOC_FREE(tmp_ctx);
7169                         return result;
7170                 }
7171                 case 7:
7172                         return publish_or_unpublish_printer(p, r->in.handle,
7173                                                             r->in.info_ctr->info.info7);
7174                 case 8:
7175                         return update_printer_devmode(p, r->in.handle,
7176                                                       r->in.devmode_ctr->devmode);
7177                 default:
7178                         return WERR_INVALID_LEVEL;
7179         }
7180 }
7181
7182 /****************************************************************
7183  _spoolss_FindClosePrinterNotify
7184 ****************************************************************/
7185
7186 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7187                                        struct spoolss_FindClosePrinterNotify *r)
7188 {
7189         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7190
7191         if (!Printer) {
7192                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7193                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7194                 return WERR_INVALID_HANDLE;
7195         }
7196
7197         if (Printer->notify.cli_chan != NULL &&
7198             Printer->notify.cli_chan->active_connections > 0) {
7199                 int snum = -1;
7200
7201                 if (Printer->printer_type == SPLHND_PRINTER) {
7202                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7203                                 return WERR_INVALID_HANDLE;
7204                         }
7205                 }
7206
7207                 srv_spoolss_replycloseprinter(snum, Printer);
7208         }
7209
7210         Printer->notify.flags=0;
7211         Printer->notify.options=0;
7212         Printer->notify.localmachine[0]='\0';
7213         Printer->notify.printerlocal=0;
7214         TALLOC_FREE(Printer->notify.option);
7215
7216         return WERR_OK;
7217 }
7218
7219 /****************************************************************
7220  _spoolss_AddJob
7221 ****************************************************************/
7222
7223 WERROR _spoolss_AddJob(struct pipes_struct *p,
7224                        struct spoolss_AddJob *r)
7225 {
7226         if (!r->in.buffer && (r->in.offered != 0)) {
7227                 return WERR_INVALID_PARAMETER;
7228         }
7229
7230         /* this is what a NT server returns for AddJob. AddJob must fail on
7231          * non-local printers */
7232
7233         if (r->in.level != 1) {
7234                 return WERR_INVALID_LEVEL;
7235         }
7236
7237         return WERR_INVALID_PARAMETER;
7238 }
7239
7240 /****************************************************************************
7241 fill_job_info1
7242 ****************************************************************************/
7243
7244 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7245                              struct spoolss_JobInfo1 *r,
7246                              const print_queue_struct *queue,
7247                              uint32_t jobid,
7248                              int position, int snum,
7249                              struct spoolss_PrinterInfo2 *pinfo2)
7250 {
7251         struct tm *t;
7252
7253         t = gmtime(&queue->time);
7254
7255         r->job_id               = jobid;
7256
7257         r->printer_name         = lp_servicename(mem_ctx, snum);
7258         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7259         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7260         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7261         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7262         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7263         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7264         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7265         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7266         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7267         r->text_status          = talloc_strdup(mem_ctx, "");
7268         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7269
7270         r->status               = nt_printj_status(queue->status);
7271         r->priority             = queue->priority;
7272         r->position             = position;
7273         r->total_pages          = queue->page_count;
7274         r->pages_printed        = 0; /* ??? */
7275
7276         init_systemtime(&r->submitted, t);
7277
7278         return WERR_OK;
7279 }
7280
7281 /****************************************************************************
7282 fill_job_info2
7283 ****************************************************************************/
7284
7285 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7286                              struct spoolss_JobInfo2 *r,
7287                              const print_queue_struct *queue,
7288                              uint32_t jobid,
7289                              int position, int snum,
7290                              struct spoolss_PrinterInfo2 *pinfo2,
7291                              struct spoolss_DeviceMode *devmode)
7292 {
7293         struct tm *t;
7294
7295         t = gmtime(&queue->time);
7296
7297         r->job_id               = jobid;
7298
7299         r->printer_name         = lp_servicename(mem_ctx, snum);
7300         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7301         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7302         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7303         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7304         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7305         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7306         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7307         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7308         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7309         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7310         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7311         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7312         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7313         r->parameters           = talloc_strdup(mem_ctx, "");
7314         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7315         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7316         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7317
7318         r->devmode              = devmode;
7319
7320         r->text_status          = talloc_strdup(mem_ctx, "");
7321         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7322
7323         r->secdesc              = NULL;
7324
7325         r->status               = nt_printj_status(queue->status);
7326         r->priority             = queue->priority;
7327         r->position             = position;
7328         r->start_time           = 0;
7329         r->until_time           = 0;
7330         r->total_pages          = queue->page_count;
7331         r->size                 = queue->size;
7332         init_systemtime(&r->submitted, t);
7333         r->time                 = 0;
7334         r->pages_printed        = 0; /* ??? */
7335
7336         return WERR_OK;
7337 }
7338
7339 /****************************************************************************
7340  Enumjobs at level 1.
7341 ****************************************************************************/
7342
7343 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7344                               const print_queue_struct *queue,
7345                               uint32_t num_queues, int snum,
7346                               struct spoolss_PrinterInfo2 *pinfo2,
7347                               union spoolss_JobInfo **info_p,
7348                               uint32_t *count)
7349 {
7350         union spoolss_JobInfo *info;
7351         int i;
7352         WERROR result = WERR_OK;
7353         uint32_t num_filled;
7354         struct tdb_print_db *pdb;
7355
7356         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7357         if (info == NULL) {
7358                 result = WERR_NOT_ENOUGH_MEMORY;
7359                 goto err_out;
7360         }
7361
7362         pdb = get_print_db_byname(pinfo2->sharename);
7363         if (pdb == NULL) {
7364                 result = WERR_INVALID_PARAMETER;
7365                 goto err_info_free;
7366         }
7367
7368         num_filled = 0;
7369         for (i = 0; i < num_queues; i++) {
7370                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7371                 if (jobid == (uint32_t)-1) {
7372                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7373                         continue;
7374                 }
7375
7376                 result = fill_job_info1(info,
7377                                         &info[num_filled].info1,
7378                                         &queue[i],
7379                                         jobid,
7380                                         i,
7381                                         snum,
7382                                         pinfo2);
7383                 if (!W_ERROR_IS_OK(result)) {
7384                         goto err_pdb_drop;
7385                 }
7386
7387                 num_filled++;
7388         }
7389
7390         release_print_db(pdb);
7391         *info_p = info;
7392         *count = num_filled;
7393
7394         return WERR_OK;
7395
7396 err_pdb_drop:
7397         release_print_db(pdb);
7398 err_info_free:
7399         TALLOC_FREE(info);
7400 err_out:
7401         *count = 0;
7402         return result;
7403 }
7404
7405 /****************************************************************************
7406  Enumjobs at level 2.
7407 ****************************************************************************/
7408
7409 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7410                               const print_queue_struct *queue,
7411                               uint32_t num_queues, int snum,
7412                               struct spoolss_PrinterInfo2 *pinfo2,
7413                               union spoolss_JobInfo **info_p,
7414                               uint32_t *count)
7415 {
7416         union spoolss_JobInfo *info;
7417         int i;
7418         WERROR result = WERR_OK;
7419         uint32_t num_filled;
7420         struct tdb_print_db *pdb;
7421
7422         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7423         if (info == NULL) {
7424                 result = WERR_NOT_ENOUGH_MEMORY;
7425                 goto err_out;
7426         }
7427
7428         pdb = get_print_db_byname(pinfo2->sharename);
7429         if (pdb == NULL) {
7430                 result = WERR_INVALID_PARAMETER;
7431                 goto err_info_free;
7432         }
7433
7434         num_filled = 0;
7435         for (i = 0; i< num_queues; i++) {
7436                 struct spoolss_DeviceMode *devmode;
7437                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7438                 if (jobid == (uint32_t)-1) {
7439                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7440                         continue;
7441                 }
7442
7443                 result = spoolss_create_default_devmode(info,
7444                                                         pinfo2->printername,
7445                                                         &devmode);
7446                 if (!W_ERROR_IS_OK(result)) {
7447                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7448                         goto err_pdb_drop;
7449                 }
7450
7451                 result = fill_job_info2(info,
7452                                         &info[num_filled].info2,
7453                                         &queue[i],
7454                                         jobid,
7455                                         i,
7456                                         snum,
7457                                         pinfo2,
7458                                         devmode);
7459                 if (!W_ERROR_IS_OK(result)) {
7460                         goto err_pdb_drop;
7461                 }
7462                 num_filled++;
7463         }
7464
7465         release_print_db(pdb);
7466         *info_p = info;
7467         *count = num_filled;
7468
7469         return WERR_OK;
7470
7471 err_pdb_drop:
7472         release_print_db(pdb);
7473 err_info_free:
7474         TALLOC_FREE(info);
7475 err_out:
7476         *count = 0;
7477         return result;
7478 }
7479
7480 /****************************************************************************
7481  Enumjobs at level 3.
7482 ****************************************************************************/
7483
7484 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7485                               const print_queue_struct *queue,
7486                               uint32_t num_queues, int snum,
7487                               struct spoolss_PrinterInfo2 *pinfo2,
7488                               union spoolss_JobInfo **info_p,
7489                               uint32_t *count)
7490 {
7491         union spoolss_JobInfo *info;
7492         int i;
7493         WERROR result = WERR_OK;
7494         uint32_t num_filled;
7495         struct tdb_print_db *pdb;
7496
7497         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7498         if (info == NULL) {
7499                 result = WERR_NOT_ENOUGH_MEMORY;
7500                 goto err_out;
7501         }
7502
7503         pdb = get_print_db_byname(pinfo2->sharename);
7504         if (pdb == NULL) {
7505                 result = WERR_INVALID_PARAMETER;
7506                 goto err_info_free;
7507         }
7508
7509         num_filled = 0;
7510         for (i = 0; i < num_queues; i++) {
7511                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7512                 if (jobid == (uint32_t)-1) {
7513                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7514                         continue;
7515                 }
7516
7517                 info[num_filled].info3.job_id = jobid;
7518                 /* next_job_id is overwritten on next iteration */
7519                 info[num_filled].info3.next_job_id = 0;
7520                 info[num_filled].info3.reserved = 0;
7521
7522                 if (num_filled > 0) {
7523                         info[num_filled - 1].info3.next_job_id = jobid;
7524                 }
7525                 num_filled++;
7526         }
7527
7528         release_print_db(pdb);
7529         *info_p = info;
7530         *count = num_filled;
7531
7532         return WERR_OK;
7533
7534 err_info_free:
7535         TALLOC_FREE(info);
7536 err_out:
7537         *count = 0;
7538         return result;
7539 }
7540
7541 /****************************************************************
7542  _spoolss_EnumJobs
7543 ****************************************************************/
7544
7545 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7546                          struct spoolss_EnumJobs *r)
7547 {
7548         WERROR result;
7549         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7550         int snum;
7551         print_status_struct prt_status;
7552         print_queue_struct *queue = NULL;
7553         uint32_t count;
7554
7555         /* that's an [in out] buffer */
7556
7557         if (!r->in.buffer && (r->in.offered != 0)) {
7558                 return WERR_INVALID_PARAMETER;
7559         }
7560
7561         if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7562                 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7563                 return WERR_INVALID_LEVEL;
7564         }
7565
7566         DEBUG(4,("_spoolss_EnumJobs\n"));
7567
7568         *r->out.needed = 0;
7569         *r->out.count = 0;
7570         *r->out.info = NULL;
7571
7572         /* lookup the printer snum and tdb entry */
7573
7574         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7575                 return WERR_INVALID_HANDLE;
7576         }
7577
7578         result = winreg_get_printer_internal(p->mem_ctx,
7579                                     get_session_info_system(),
7580                                     p->msg_ctx,
7581                                     lp_const_servicename(snum),
7582                                     &pinfo2);
7583         if (!W_ERROR_IS_OK(result)) {
7584                 return result;
7585         }
7586
7587         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7588         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7589                 count, prt_status.status, prt_status.message));
7590
7591         if (count == 0) {
7592                 SAFE_FREE(queue);
7593                 TALLOC_FREE(pinfo2);
7594                 return WERR_OK;
7595         }
7596
7597         switch (r->in.level) {
7598         case 1:
7599                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7600                                          pinfo2, r->out.info, r->out.count);
7601                 break;
7602         case 2:
7603                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7604                                          pinfo2, r->out.info, r->out.count);
7605                 break;
7606         case 3:
7607                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7608                                          pinfo2, r->out.info, r->out.count);
7609                 break;
7610         default:
7611                 SMB_ASSERT(false);      /* level checked on entry */
7612                 break;
7613         }
7614
7615         SAFE_FREE(queue);
7616         TALLOC_FREE(pinfo2);
7617
7618         if (!W_ERROR_IS_OK(result)) {
7619                 return result;
7620         }
7621
7622         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7623                                                      spoolss_EnumJobs,
7624                                                      *r->out.info, r->in.level,
7625                                                      *r->out.count);
7626         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7627         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7628
7629         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7630 }
7631
7632 /****************************************************************
7633  _spoolss_ScheduleJob
7634 ****************************************************************/
7635
7636 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7637                             struct spoolss_ScheduleJob *r)
7638 {
7639         return WERR_OK;
7640 }
7641
7642 /****************************************************************
7643 ****************************************************************/
7644
7645 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7646                                struct messaging_context *msg_ctx,
7647                                const char *printer_name,
7648                                uint32_t job_id,
7649                                struct spoolss_SetJobInfo1 *r)
7650 {
7651         char *old_doc_name;
7652
7653         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7654                 return WERR_INVALID_HANDLE;
7655         }
7656
7657         if (strequal(old_doc_name, r->document_name)) {
7658                 return WERR_OK;
7659         }
7660
7661         if (!print_job_set_name(server_event_context(), msg_ctx,
7662                                 printer_name, job_id, r->document_name)) {
7663                 return WERR_INVALID_HANDLE;
7664         }
7665
7666         return WERR_OK;
7667 }
7668
7669 /****************************************************************
7670  _spoolss_SetJob
7671 ****************************************************************/
7672
7673 WERROR _spoolss_SetJob(struct pipes_struct *p,
7674                        struct spoolss_SetJob *r)
7675 {
7676         const struct auth_session_info *session_info = p->session_info;
7677         int snum;
7678         WERROR errcode = WERR_INVALID_FUNCTION;
7679
7680         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7681                 return WERR_INVALID_HANDLE;
7682         }
7683
7684         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7685                 return WERR_INVALID_PRINTER_NAME;
7686         }
7687
7688         switch (r->in.command) {
7689         case SPOOLSS_JOB_CONTROL_CANCEL:
7690         case SPOOLSS_JOB_CONTROL_DELETE:
7691                 errcode = print_job_delete(session_info, p->msg_ctx,
7692                                            snum, r->in.job_id);
7693                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7694                         errcode = WERR_OK;
7695                 }
7696                 break;
7697         case SPOOLSS_JOB_CONTROL_PAUSE:
7698                 errcode = print_job_pause(session_info, p->msg_ctx,
7699                                           snum, r->in.job_id);
7700                 break;
7701         case SPOOLSS_JOB_CONTROL_RESTART:
7702         case SPOOLSS_JOB_CONTROL_RESUME:
7703                 errcode = print_job_resume(session_info, p->msg_ctx,
7704                                            snum, r->in.job_id);
7705                 break;
7706         case SPOOLSS_JOB_CONTROL_NOOP:
7707                 errcode = WERR_OK;
7708                 break;
7709         default:
7710                 return WERR_INVALID_LEVEL;
7711         }
7712
7713         if (!W_ERROR_IS_OK(errcode)) {
7714                 return errcode;
7715         }
7716
7717         if (r->in.ctr == NULL) {
7718                 return errcode;
7719         }
7720
7721         switch (r->in.ctr->level) {
7722         case 1:
7723                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7724                                            lp_const_servicename(snum),
7725                                            r->in.job_id,
7726                                            r->in.ctr->info.info1);
7727                 break;
7728         case 2:
7729         case 3:
7730         case 4:
7731         default:
7732                 return WERR_INVALID_LEVEL;
7733         }
7734
7735         return errcode;
7736 }
7737
7738 /****************************************************************************
7739  Enumerates all printer drivers by level and architecture.
7740 ****************************************************************************/
7741
7742 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7743                                                        const struct auth_session_info *session_info,
7744                                                        struct messaging_context *msg_ctx,
7745                                                        const char *servername,
7746                                                        const char *architecture,
7747                                                        uint32_t level,
7748                                                        union spoolss_DriverInfo **info_p,
7749                                                        uint32_t *count_p)
7750 {
7751         int i;
7752         uint32_t version;
7753         struct spoolss_DriverInfo8 *driver;
7754         union spoolss_DriverInfo *info = NULL;
7755         uint32_t count = 0;
7756         WERROR result = WERR_OK;
7757         uint32_t num_drivers;
7758         const char **drivers;
7759         struct dcerpc_binding_handle *b;
7760         TALLOC_CTX *tmp_ctx = NULL;
7761
7762         *count_p = 0;
7763         *info_p = NULL;
7764
7765         tmp_ctx = talloc_new(mem_ctx);
7766         if (!tmp_ctx) {
7767                 return WERR_NOT_ENOUGH_MEMORY;
7768         }
7769
7770         result = winreg_printer_binding_handle(tmp_ctx,
7771                                                session_info,
7772                                                msg_ctx,
7773                                                &b);
7774         if (!W_ERROR_IS_OK(result)) {
7775                 goto out;
7776         }
7777
7778         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7779                 result = winreg_get_driver_list(tmp_ctx, b,
7780                                                 architecture, version,
7781                                                 &num_drivers, &drivers);
7782                 if (!W_ERROR_IS_OK(result)) {
7783                         goto out;
7784                 }
7785                 DEBUG(4, ("we have:[%d] drivers in environment"
7786                           " [%s] and version [%d]\n",
7787                           num_drivers, architecture, version));
7788
7789                 if (num_drivers != 0) {
7790                         info = talloc_realloc(tmp_ctx, info,
7791                                                     union spoolss_DriverInfo,
7792                                                     count + num_drivers);
7793                         if (!info) {
7794                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7795                                         "failed to enlarge driver info buffer!\n"));
7796                                 result = WERR_NOT_ENOUGH_MEMORY;
7797                                 goto out;
7798                         }
7799                 }
7800
7801                 for (i = 0; i < num_drivers; i++) {
7802                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7803
7804                         result = winreg_get_driver(tmp_ctx, b,
7805                                                    architecture, drivers[i],
7806                                                    version, &driver);
7807                         if (!W_ERROR_IS_OK(result)) {
7808                                 goto out;
7809                         }
7810
7811                         switch (level) {
7812                         case 1:
7813                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7814                                                                    driver, servername);
7815                                 break;
7816                         case 2:
7817                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7818                                                                    driver, servername);
7819                                 break;
7820                         case 3:
7821                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7822                                                                    driver, servername);
7823                                 break;
7824                         case 4:
7825                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7826                                                                    driver, servername);
7827                                 break;
7828                         case 5:
7829                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7830                                                                    driver, servername);
7831                                 break;
7832                         case 6:
7833                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7834                                                                    driver, servername);
7835                                 break;
7836                         case 8:
7837                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7838                                                                    driver, servername);
7839                                 break;
7840                         default:
7841                                 result = WERR_INVALID_LEVEL;
7842                                 break;
7843                         }
7844
7845                         TALLOC_FREE(driver);
7846
7847                         if (!W_ERROR_IS_OK(result)) {
7848                                 goto out;
7849                         }
7850                 }
7851
7852                 count += num_drivers;
7853                 TALLOC_FREE(drivers);
7854         }
7855
7856 out:
7857         if (W_ERROR_IS_OK(result)) {
7858                 *info_p = talloc_move(mem_ctx, &info);
7859                 *count_p = count;
7860         }
7861
7862         talloc_free(tmp_ctx);
7863         return result;
7864 }
7865
7866 /****************************************************************************
7867  Enumerates all printer drivers by level.
7868 ****************************************************************************/
7869
7870 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7871                                        const struct auth_session_info *session_info,
7872                                        struct messaging_context *msg_ctx,
7873                                        const char *servername,
7874                                        const char *architecture,
7875                                        uint32_t level,
7876                                        union spoolss_DriverInfo **info_p,
7877                                        uint32_t *count_p)
7878 {
7879         uint32_t a,i;
7880         WERROR result = WERR_OK;
7881
7882         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7883
7884                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7885
7886                         union spoolss_DriverInfo *info = NULL;
7887                         uint32_t count = 0;
7888
7889                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7890                                                                           session_info,
7891                                                                           msg_ctx,
7892                                                                           servername,
7893                                                                           archi_table[a].long_archi,
7894                                                                           level,
7895                                                                           &info,
7896                                                                           &count);
7897                         if (!W_ERROR_IS_OK(result)) {
7898                                 continue;
7899                         }
7900
7901                         for (i=0; i < count; i++) {
7902                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7903                                              info[i], info_p, count_p);
7904                         }
7905                 }
7906
7907                 return result;
7908         }
7909
7910         return enumprinterdrivers_level_by_architecture(mem_ctx,
7911                                                         session_info,
7912                                                         msg_ctx,
7913                                                         servername,
7914                                                         architecture,
7915                                                         level,
7916                                                         info_p,
7917                                                         count_p);
7918 }
7919
7920 /****************************************************************
7921  _spoolss_EnumPrinterDrivers
7922 ****************************************************************/
7923
7924 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7925                                    struct spoolss_EnumPrinterDrivers *r)
7926 {
7927         const char *cservername;
7928         WERROR result;
7929
7930         /* that's an [in out] buffer */
7931
7932         if (!r->in.buffer && (r->in.offered != 0)) {
7933                 return WERR_INVALID_PARAMETER;
7934         }
7935
7936         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7937
7938         *r->out.needed = 0;
7939         *r->out.count = 0;
7940         *r->out.info = NULL;
7941
7942         cservername = canon_servername(r->in.server);
7943
7944         if (!is_myname_or_ipaddr(cservername)) {
7945                 return WERR_UNKNOWN_PRINTER_DRIVER;
7946         }
7947
7948         result = enumprinterdrivers_level(p->mem_ctx,
7949                                           get_session_info_system(),
7950                                           p->msg_ctx,
7951                                           cservername,
7952                                           r->in.environment,
7953                                           r->in.level,
7954                                           r->out.info,
7955                                           r->out.count);
7956         if (!W_ERROR_IS_OK(result)) {
7957                 return result;
7958         }
7959
7960         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7961                                                      spoolss_EnumPrinterDrivers,
7962                                                      *r->out.info, r->in.level,
7963                                                      *r->out.count);
7964         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7965         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7966
7967         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7968 }
7969
7970 /****************************************************************
7971  _spoolss_EnumForms
7972 ****************************************************************/
7973
7974 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7975                           struct spoolss_EnumForms *r)
7976 {
7977         WERROR result;
7978
7979         *r->out.count = 0;
7980         *r->out.needed = 0;
7981         *r->out.info = NULL;
7982
7983         /* that's an [in out] buffer */
7984
7985         if (!r->in.buffer && (r->in.offered != 0) ) {
7986                 return WERR_INVALID_PARAMETER;
7987         }
7988
7989         DEBUG(4,("_spoolss_EnumForms\n"));
7990         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7991         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7992
7993         switch (r->in.level) {
7994         case 1:
7995                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7996                                                    get_session_info_system(),
7997                                                    p->msg_ctx,
7998                                                    r->out.count,
7999                                                    r->out.info);
8000                 break;
8001         default:
8002                 result = WERR_INVALID_LEVEL;
8003                 break;
8004         }
8005
8006         if (!W_ERROR_IS_OK(result)) {
8007                 return result;
8008         }
8009
8010         if (*r->out.count == 0) {
8011                 return WERR_NO_MORE_ITEMS;
8012         }
8013
8014         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8015                                                      spoolss_EnumForms,
8016                                                      *r->out.info, r->in.level,
8017                                                      *r->out.count);
8018         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8019         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8020
8021         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8022 }
8023
8024 /****************************************************************
8025  _spoolss_GetForm
8026 ****************************************************************/
8027
8028 WERROR _spoolss_GetForm(struct pipes_struct *p,
8029                         struct spoolss_GetForm *r)
8030 {
8031         WERROR result;
8032
8033         /* that's an [in out] buffer */
8034
8035         if (!r->in.buffer && (r->in.offered != 0)) {
8036                 TALLOC_FREE(r->out.info);
8037                 return WERR_INVALID_PARAMETER;
8038         }
8039
8040         DEBUG(4,("_spoolss_GetForm\n"));
8041         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8042         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
8043
8044         switch (r->in.level) {
8045         case 1:
8046                 result = winreg_printer_getform1_internal(p->mem_ctx,
8047                                                  get_session_info_system(),
8048                                                  p->msg_ctx,
8049                                                  r->in.form_name,
8050                                                  &r->out.info->info1);
8051                 break;
8052         default:
8053                 result = WERR_INVALID_LEVEL;
8054                 break;
8055         }
8056
8057         if (!W_ERROR_IS_OK(result)) {
8058                 TALLOC_FREE(r->out.info);
8059                 return result;
8060         }
8061
8062         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
8063                                                r->out.info, r->in.level);
8064         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8065
8066         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8067 }
8068
8069 /****************************************************************************
8070 ****************************************************************************/
8071
8072 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
8073                           struct spoolss_PortInfo1 *r,
8074                           const char *name)
8075 {
8076         r->port_name = talloc_strdup(mem_ctx, name);
8077         W_ERROR_HAVE_NO_MEMORY(r->port_name);
8078
8079         return WERR_OK;
8080 }
8081
8082 /****************************************************************************
8083  TODO: This probably needs distinguish between TCP/IP and Local ports
8084  somehow.
8085 ****************************************************************************/
8086
8087 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
8088                           struct spoolss_PortInfo2 *r,
8089                           const char *name)
8090 {
8091         r->port_name = talloc_strdup(mem_ctx, name);
8092         W_ERROR_HAVE_NO_MEMORY(r->port_name);
8093
8094         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
8095         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8096
8097         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
8098         W_ERROR_HAVE_NO_MEMORY(r->description);
8099
8100         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
8101         r->reserved = 0;
8102
8103         return WERR_OK;
8104 }
8105
8106
8107 /****************************************************************************
8108  wrapper around the enumer ports command
8109 ****************************************************************************/
8110
8111 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
8112 {
8113         char *cmd = lp_enumports_command(talloc_tos());
8114         char **qlines = NULL;
8115         char *command = NULL;
8116         int numlines;
8117         int ret;
8118         int fd;
8119
8120         *count = 0;
8121         *lines = NULL;
8122
8123         /* if no hook then just fill in the default port */
8124
8125         if ( !*cmd ) {
8126                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
8127                         return WERR_NOT_ENOUGH_MEMORY;
8128                 }
8129                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
8130                         TALLOC_FREE(qlines);
8131                         return WERR_NOT_ENOUGH_MEMORY;
8132                 }
8133                 qlines[1] = NULL;
8134                 numlines = 1;
8135         }
8136         else {
8137                 /* we have a valid enumport command */
8138
8139                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
8140                 if (!command) {
8141                         return WERR_NOT_ENOUGH_MEMORY;
8142                 }
8143
8144                 DEBUG(10,("Running [%s]\n", command));
8145                 ret = smbrun(command, &fd);
8146                 DEBUG(10,("Returned [%d]\n", ret));
8147                 TALLOC_FREE(command);
8148                 if (ret != 0) {
8149                         if (fd != -1) {
8150                                 close(fd);
8151                         }
8152                         return WERR_ACCESS_DENIED;
8153                 }
8154
8155                 numlines = 0;
8156                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
8157                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8158                 close(fd);
8159         }
8160
8161         *count = numlines;
8162         *lines = qlines;
8163
8164         return WERR_OK;
8165 }
8166
8167 /****************************************************************************
8168  enumports level 1.
8169 ****************************************************************************/
8170
8171 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8172                                 union spoolss_PortInfo **info_p,
8173                                 uint32_t *count)
8174 {
8175         union spoolss_PortInfo *info = NULL;
8176         int i=0;
8177         WERROR result = WERR_OK;
8178         char **qlines = NULL;
8179         int numlines = 0;
8180
8181         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8182         if (!W_ERROR_IS_OK(result)) {
8183                 goto out;
8184         }
8185
8186         if (numlines) {
8187                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8188                 if (!info) {
8189                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8190                         result = WERR_NOT_ENOUGH_MEMORY;
8191                         goto out;
8192                 }
8193
8194                 for (i=0; i<numlines; i++) {
8195                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8196                         result = fill_port_1(info, &info[i].info1, qlines[i]);
8197                         if (!W_ERROR_IS_OK(result)) {
8198                                 goto out;
8199                         }
8200                 }
8201         }
8202         TALLOC_FREE(qlines);
8203
8204 out:
8205         if (!W_ERROR_IS_OK(result)) {
8206                 TALLOC_FREE(info);
8207                 TALLOC_FREE(qlines);
8208                 *count = 0;
8209                 *info_p = NULL;
8210                 return result;
8211         }
8212
8213         *info_p = info;
8214         *count = numlines;
8215
8216         return WERR_OK;
8217 }
8218
8219 /****************************************************************************
8220  enumports level 2.
8221 ****************************************************************************/
8222
8223 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8224                                 union spoolss_PortInfo **info_p,
8225                                 uint32_t *count)
8226 {
8227         union spoolss_PortInfo *info = NULL;
8228         int i=0;
8229         WERROR result = WERR_OK;
8230         char **qlines = NULL;
8231         int numlines = 0;
8232
8233         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8234         if (!W_ERROR_IS_OK(result)) {
8235                 goto out;
8236         }
8237
8238         if (numlines) {
8239                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8240                 if (!info) {
8241                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8242                         result = WERR_NOT_ENOUGH_MEMORY;
8243                         goto out;
8244                 }
8245
8246                 for (i=0; i<numlines; i++) {
8247                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8248                         result = fill_port_2(info, &info[i].info2, qlines[i]);
8249                         if (!W_ERROR_IS_OK(result)) {
8250                                 goto out;
8251                         }
8252                 }
8253         }
8254         TALLOC_FREE(qlines);
8255
8256 out:
8257         if (!W_ERROR_IS_OK(result)) {
8258                 TALLOC_FREE(info);
8259                 TALLOC_FREE(qlines);
8260                 *count = 0;
8261                 *info_p = NULL;
8262                 return result;
8263         }
8264
8265         *info_p = info;
8266         *count = numlines;
8267
8268         return WERR_OK;
8269 }
8270
8271 /****************************************************************
8272  _spoolss_EnumPorts
8273 ****************************************************************/
8274
8275 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8276                           struct spoolss_EnumPorts *r)
8277 {
8278         WERROR result;
8279
8280         /* that's an [in out] buffer */
8281
8282         if (!r->in.buffer && (r->in.offered != 0)) {
8283                 return WERR_INVALID_PARAMETER;
8284         }
8285
8286         DEBUG(4,("_spoolss_EnumPorts\n"));
8287
8288         *r->out.count = 0;
8289         *r->out.needed = 0;
8290         *r->out.info = NULL;
8291
8292         switch (r->in.level) {
8293         case 1:
8294                 result = enumports_level_1(p->mem_ctx, r->out.info,
8295                                            r->out.count);
8296                 break;
8297         case 2:
8298                 result = enumports_level_2(p->mem_ctx, r->out.info,
8299                                            r->out.count);
8300                 break;
8301         default:
8302                 return WERR_INVALID_LEVEL;
8303         }
8304
8305         if (!W_ERROR_IS_OK(result)) {
8306                 return result;
8307         }
8308
8309         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8310                                                      spoolss_EnumPorts,
8311                                                      *r->out.info, r->in.level,
8312                                                      *r->out.count);
8313         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8314         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8315
8316         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8317 }
8318
8319 /****************************************************************************
8320 ****************************************************************************/
8321
8322 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8323                                            const char *server,
8324                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8325                                            struct spoolss_DeviceMode *devmode,
8326                                            struct security_descriptor *secdesc,
8327                                            struct spoolss_UserLevelCtr *user_ctr,
8328                                            struct policy_handle *handle)
8329 {
8330         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8331         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8332         int     snum;
8333         WERROR err = WERR_OK;
8334
8335         /* samba does not have a concept of local, non-shared printers yet, so
8336          * make sure we always setup sharename - gd */
8337         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8338             (info2->printername != NULL && info2->printername[0] != '\0')) {
8339                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8340                         "no sharename has been set, setting printername %s as sharename\n",
8341                         info2->printername));
8342                 info2->sharename = info2->printername;
8343         }
8344
8345         /* check to see if the printer already exists */
8346         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8347                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8348                         info2->sharename));
8349                 return WERR_PRINTER_ALREADY_EXISTS;
8350         }
8351
8352         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8353                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8354                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8355                                 info2->printername));
8356                         return WERR_PRINTER_ALREADY_EXISTS;
8357                 }
8358         }
8359
8360         /* validate printer info struct */
8361         if (!info2->printername || strlen(info2->printername) == 0) {
8362                 return WERR_INVALID_PRINTER_NAME;
8363         }
8364         if (!info2->portname || strlen(info2->portname) == 0) {
8365                 return WERR_UNKNOWN_PORT;
8366         }
8367         if (!info2->drivername || strlen(info2->drivername) == 0) {
8368                 return WERR_UNKNOWN_PRINTER_DRIVER;
8369         }
8370         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8371                 return WERR_UNKNOWN_PRINTPROCESSOR;
8372         }
8373
8374         /* FIXME!!!  smbd should check to see if the driver is installed before
8375            trying to add a printer like this  --jerry */
8376
8377         if (*lp_addprinter_command(talloc_tos()) ) {
8378                 char *raddr;
8379
8380                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8381                                                          p->mem_ctx);
8382                 if (raddr == NULL) {
8383                         return WERR_NOT_ENOUGH_MEMORY;
8384                 }
8385
8386                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8387                                        info2, raddr,
8388                                        p->msg_ctx) ) {
8389                         return WERR_ACCESS_DENIED;
8390                 }
8391         } else {
8392                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8393                         "smb.conf parameter \"addprinter command\" is defined. This "
8394                         "parameter must exist for this call to succeed\n",
8395                         info2->sharename ));
8396         }
8397
8398         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8399                 return WERR_ACCESS_DENIED;
8400         }
8401
8402         /* you must be a printer admin to add a new printer */
8403         if (!W_ERROR_IS_OK(print_access_check(p->session_info,
8404                                               p->msg_ctx,
8405                                               snum,
8406                                               PRINTER_ACCESS_ADMINISTER))) {
8407                 return WERR_ACCESS_DENIED;
8408         }
8409
8410         /*
8411          * Do sanity check on the requested changes for Samba.
8412          */
8413
8414         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8415                 return WERR_INVALID_PARAMETER;
8416         }
8417
8418         if (devmode == NULL) {
8419                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8420         }
8421
8422         err = update_dsspooler(p->mem_ctx,
8423                                get_session_info_system(),
8424                                p->msg_ctx,
8425                                0,
8426                                info2,
8427                                NULL);
8428         if (!W_ERROR_IS_OK(err)) {
8429                 return err;
8430         }
8431
8432         err = winreg_update_printer_internal(p->mem_ctx,
8433                                     get_session_info_system(),
8434                                     p->msg_ctx,
8435                                     info2->sharename,
8436                                     info2_mask,
8437                                     info2,
8438                                     devmode,
8439                                     secdesc);
8440         if (!W_ERROR_IS_OK(err)) {
8441                 return err;
8442         }
8443
8444         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8445         if (!W_ERROR_IS_OK(err)) {
8446                 /* Handle open failed - remove addition. */
8447                 ZERO_STRUCTP(handle);
8448                 return err;
8449         }
8450
8451         return WERR_OK;
8452 }
8453
8454 /****************************************************************
8455  _spoolss_AddPrinterEx
8456 ****************************************************************/
8457
8458 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8459                              struct spoolss_AddPrinterEx *r)
8460 {
8461         switch (r->in.info_ctr->level) {
8462         case 1:
8463                 /* we don't handle yet */
8464                 /* but I know what to do ... */
8465                 return WERR_INVALID_LEVEL;
8466         case 2:
8467                 return spoolss_addprinterex_level_2(p, r->in.server,
8468                                                     r->in.info_ctr,
8469                                                     r->in.devmode_ctr->devmode,
8470                                                     r->in.secdesc_ctr->sd,
8471                                                     r->in.userlevel_ctr,
8472                                                     r->out.handle);
8473         default:
8474                 return WERR_INVALID_LEVEL;
8475         }
8476 }
8477
8478 /****************************************************************
8479  _spoolss_AddPrinter
8480 ****************************************************************/
8481
8482 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8483                            struct spoolss_AddPrinter *r)
8484 {
8485         struct spoolss_AddPrinterEx a;
8486         struct spoolss_UserLevelCtr userlevel_ctr;
8487
8488         ZERO_STRUCT(userlevel_ctr);
8489
8490         userlevel_ctr.level = 1;
8491
8492         a.in.server             = r->in.server;
8493         a.in.info_ctr           = r->in.info_ctr;
8494         a.in.devmode_ctr        = r->in.devmode_ctr;
8495         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8496         a.in.userlevel_ctr      = &userlevel_ctr;
8497         a.out.handle            = r->out.handle;
8498
8499         return _spoolss_AddPrinterEx(p, &a);
8500 }
8501
8502 /****************************************************************
8503  _spoolss_AddPrinterDriverEx
8504 ****************************************************************/
8505
8506 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8507                                    struct spoolss_AddPrinterDriverEx *r)
8508 {
8509         WERROR err = WERR_OK;
8510         const char *driver_name = NULL;
8511         uint32_t version;
8512         /*
8513          * we only support the semantics of AddPrinterDriver()
8514          * i.e. only copy files that are newer than existing ones
8515          */
8516
8517         if (r->in.flags == 0) {
8518                 return WERR_INVALID_PARAMETER;
8519         }
8520
8521         if (r->in.flags != APD_COPY_NEW_FILES) {
8522                 return WERR_ACCESS_DENIED;
8523         }
8524
8525         /* FIXME */
8526         if (r->in.info_ctr->level != 3 &&
8527             r->in.info_ctr->level != 6 &&
8528             r->in.info_ctr->level != 8) {
8529                 DEBUG(0,("%s: level %d not yet implemented\n", __func__,
8530                         r->in.info_ctr->level));
8531                 return WERR_INVALID_LEVEL;
8532         }
8533
8534         DEBUG(5,("Cleaning driver's information\n"));
8535         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8536         if (!W_ERROR_IS_OK(err))
8537                 goto done;
8538
8539         DEBUG(5,("Moving driver to final destination\n"));
8540         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8541         if (!W_ERROR_IS_OK(err)) {
8542                 goto done;
8543         }
8544
8545         err = winreg_add_driver_internal(p->mem_ctx,
8546                                 get_session_info_system(),
8547                                 p->msg_ctx,
8548                                 r->in.info_ctr,
8549                                 &driver_name,
8550                                 &version);
8551         if (!W_ERROR_IS_OK(err)) {
8552                 goto done;
8553         }
8554
8555         /*
8556          * I think this is where he DrvUpgradePrinter() hook would be
8557          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8558          * server.  Right now, we just need to send ourselves a message
8559          * to update each printer bound to this driver.   --jerry
8560          */
8561
8562         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8563                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8564                         __func__, driver_name));
8565         }
8566
8567 done:
8568         return err;
8569 }
8570
8571 /****************************************************************
8572  _spoolss_AddPrinterDriver
8573 ****************************************************************/
8574
8575 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8576                                  struct spoolss_AddPrinterDriver *r)
8577 {
8578         struct spoolss_AddPrinterDriverEx a;
8579
8580         switch (r->in.info_ctr->level) {
8581         case 2:
8582         case 3:
8583         case 4:
8584         case 5:
8585                 break;
8586         default:
8587                 return WERR_INVALID_LEVEL;
8588         }
8589
8590         a.in.servername         = r->in.servername;
8591         a.in.info_ctr           = r->in.info_ctr;
8592         a.in.flags              = APD_COPY_NEW_FILES;
8593
8594         return _spoolss_AddPrinterDriverEx(p, &a);
8595 }
8596
8597 /****************************************************************************
8598 ****************************************************************************/
8599
8600 struct _spoolss_paths {
8601         int type;
8602         const char *share;
8603         const char *dir;
8604 };
8605
8606 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8607
8608 static const struct _spoolss_paths spoolss_paths[]= {
8609         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8610         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8611 };
8612
8613 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8614                                           const char *servername,
8615                                           const char *environment,
8616                                           int component,
8617                                           char **path)
8618 {
8619         const char *pservername = NULL;
8620         const char *long_archi;
8621         const char *short_archi;
8622
8623         *path = NULL;
8624
8625         /* environment may be empty */
8626         if (environment && strlen(environment)) {
8627                 long_archi = environment;
8628         } else {
8629                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8630                                                   "spoolss", "architecture",
8631                                                   SPOOLSS_ARCHITECTURE_NT_X86);
8632         }
8633
8634         /* servername may be empty */
8635         if (servername && strlen(servername)) {
8636                 pservername = canon_servername(servername);
8637
8638                 if (!is_myname_or_ipaddr(pservername)) {
8639                         return WERR_INVALID_PARAMETER;
8640                 }
8641         }
8642
8643         if (!(short_archi = get_short_archi(long_archi))) {
8644                 return WERR_INVALID_ENVIRONMENT;
8645         }
8646
8647         switch (component) {
8648         case SPOOLSS_PRTPROCS_PATH:
8649         case SPOOLSS_DRIVER_PATH:
8650                 if (pservername) {
8651                         *path = talloc_asprintf(mem_ctx,
8652                                         "\\\\%s\\%s\\%s",
8653                                         pservername,
8654                                         spoolss_paths[component].share,
8655                                         short_archi);
8656                 } else {
8657                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8658                                         SPOOLSS_DEFAULT_SERVER_PATH,
8659                                         spoolss_paths[component].dir,
8660                                         short_archi);
8661                 }
8662                 break;
8663         default:
8664                 return WERR_INVALID_PARAMETER;
8665         }
8666
8667         if (!*path) {
8668                 return WERR_NOT_ENOUGH_MEMORY;
8669         }
8670
8671         return WERR_OK;
8672 }
8673
8674 /****************************************************************************
8675 ****************************************************************************/
8676
8677 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8678                                           const char *servername,
8679                                           const char *environment,
8680                                           struct spoolss_DriverDirectoryInfo1 *r)
8681 {
8682         WERROR werr;
8683         char *path = NULL;
8684
8685         werr = compose_spoolss_server_path(mem_ctx,
8686                                            servername,
8687                                            environment,
8688                                            SPOOLSS_DRIVER_PATH,
8689                                            &path);
8690         if (!W_ERROR_IS_OK(werr)) {
8691                 return werr;
8692         }
8693
8694         DEBUG(4,("printer driver directory: [%s]\n", path));
8695
8696         r->directory_name = path;
8697
8698         return WERR_OK;
8699 }
8700
8701 /****************************************************************
8702  _spoolss_GetPrinterDriverDirectory
8703 ****************************************************************/
8704
8705 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8706                                           struct spoolss_GetPrinterDriverDirectory *r)
8707 {
8708         WERROR werror;
8709
8710         /* that's an [in out] buffer */
8711
8712         if (!r->in.buffer && (r->in.offered != 0)) {
8713                 TALLOC_FREE(r->out.info);
8714                 return WERR_INVALID_PARAMETER;
8715         }
8716
8717         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8718                 r->in.level));
8719
8720         *r->out.needed = 0;
8721
8722         /* r->in.level is ignored */
8723
8724         werror = getprinterdriverdir_level_1(p->mem_ctx,
8725                                              r->in.server,
8726                                              r->in.environment,
8727                                              &r->out.info->info1);
8728         if (!W_ERROR_IS_OK(werror)) {
8729                 TALLOC_FREE(r->out.info);
8730                 return werror;
8731         }
8732
8733         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8734                                                r->out.info, r->in.level);
8735         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8736
8737         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8738 }
8739
8740 /****************************************************************
8741  _spoolss_EnumPrinterData
8742 ****************************************************************/
8743
8744 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8745                                 struct spoolss_EnumPrinterData *r)
8746 {
8747         WERROR result;
8748         struct spoolss_EnumPrinterDataEx r2;
8749         uint32_t count;
8750         struct spoolss_PrinterEnumValues *info, *val = NULL;
8751         uint32_t needed;
8752
8753         r2.in.handle    = r->in.handle;
8754         r2.in.key_name  = "PrinterDriverData";
8755         r2.in.offered   = 0;
8756         r2.out.count    = &count;
8757         r2.out.info     = &info;
8758         r2.out.needed   = &needed;
8759
8760         result = _spoolss_EnumPrinterDataEx(p, &r2);
8761         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8762                 r2.in.offered = needed;
8763                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8764         }
8765         if (!W_ERROR_IS_OK(result)) {
8766                 return result;
8767         }
8768
8769         /*
8770          * The NT machine wants to know the biggest size of value and data
8771          *
8772          * cf: MSDN EnumPrinterData remark section
8773          */
8774
8775         if (!r->in.value_offered && !r->in.data_offered) {
8776                 uint32_t biggest_valuesize = 0;
8777                 uint32_t biggest_datasize = 0;
8778                 int i, name_length;
8779
8780                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8781
8782                 for (i=0; i<count; i++) {
8783
8784                         name_length = strlen(info[i].value_name);
8785                         if (strlen(info[i].value_name) > biggest_valuesize) {
8786                                 biggest_valuesize = name_length;
8787                         }
8788
8789                         if (info[i].data_length > biggest_datasize) {
8790                                 biggest_datasize = info[i].data_length;
8791                         }
8792
8793                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8794                                 biggest_datasize));
8795                 }
8796
8797                 /* the value is an UNICODE string but real_value_size is the length
8798                    in bytes including the trailing 0 */
8799
8800                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8801                 *r->out.data_needed  = biggest_datasize;
8802
8803                 DEBUG(6,("final values: [%d], [%d]\n",
8804                         *r->out.value_needed, *r->out.data_needed));
8805
8806                 return WERR_OK;
8807         }
8808
8809         if (r->in.enum_index < count) {
8810                 val = &info[r->in.enum_index];
8811         }
8812
8813         if (val == NULL) {
8814                 /* out_value should default to "" or else NT4 has
8815                    problems unmarshalling the response */
8816
8817                 if (r->in.value_offered) {
8818                         *r->out.value_needed = 1;
8819                         r->out.value_name = talloc_strdup(r, "");
8820                         if (!r->out.value_name) {
8821                                 return WERR_NOT_ENOUGH_MEMORY;
8822                         }
8823                 } else {
8824                         r->out.value_name = NULL;
8825                         *r->out.value_needed = 0;
8826                 }
8827
8828                 /* the data is counted in bytes */
8829
8830                 *r->out.data_needed = r->in.data_offered;
8831
8832                 result = WERR_NO_MORE_ITEMS;
8833         } else {
8834                 /*
8835                  * the value is:
8836                  * - counted in bytes in the request
8837                  * - counted in UNICODE chars in the max reply
8838                  * - counted in bytes in the real size
8839                  *
8840                  * take a pause *before* coding not *during* coding
8841                  */
8842
8843                 /* name */
8844                 if (r->in.value_offered) {
8845                         r->out.value_name = talloc_strdup(r, val->value_name);
8846                         if (!r->out.value_name) {
8847                                 return WERR_NOT_ENOUGH_MEMORY;
8848                         }
8849                         *r->out.value_needed = val->value_name_len;
8850                 } else {
8851                         r->out.value_name = NULL;
8852                         *r->out.value_needed = 0;
8853                 }
8854
8855                 /* type */
8856
8857                 *r->out.type = val->type;
8858
8859                 /* data - counted in bytes */
8860
8861                 /*
8862                  * See the section "Dynamically Typed Query Parameters"
8863                  * in MS-RPRN.
8864                  */
8865
8866                 if (r->out.data && val->data && val->data->data &&
8867                                 val->data_length && r->in.data_offered) {
8868                         memcpy(r->out.data, val->data->data,
8869                                 MIN(val->data_length,r->in.data_offered));
8870                 }
8871
8872                 *r->out.data_needed = val->data_length;
8873
8874                 result = WERR_OK;
8875         }
8876
8877         return result;
8878 }
8879
8880 /****************************************************************
8881  _spoolss_SetPrinterData
8882 ****************************************************************/
8883
8884 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8885                                struct spoolss_SetPrinterData *r)
8886 {
8887         struct spoolss_SetPrinterDataEx r2;
8888
8889         r2.in.handle            = r->in.handle;
8890         r2.in.key_name          = "PrinterDriverData";
8891         r2.in.value_name        = r->in.value_name;
8892         r2.in.type              = r->in.type;
8893         r2.in.data              = r->in.data;
8894         r2.in.offered           = r->in.offered;
8895
8896         return _spoolss_SetPrinterDataEx(p, &r2);
8897 }
8898
8899 /****************************************************************
8900  _spoolss_ResetPrinter
8901 ****************************************************************/
8902
8903 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8904                              struct spoolss_ResetPrinter *r)
8905 {
8906         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8907         int             snum;
8908
8909         DEBUG(5,("_spoolss_ResetPrinter\n"));
8910
8911         /*
8912          * All we do is to check to see if the handle and queue is valid.
8913          * This call really doesn't mean anything to us because we only
8914          * support RAW printing.   --jerry
8915          */
8916
8917         if (!Printer) {
8918                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8919                         OUR_HANDLE(r->in.handle)));
8920                 return WERR_INVALID_HANDLE;
8921         }
8922
8923         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8924                 return WERR_INVALID_HANDLE;
8925
8926
8927         /* blindly return success */
8928         return WERR_OK;
8929 }
8930
8931 /****************************************************************
8932  _spoolss_DeletePrinterData
8933 ****************************************************************/
8934
8935 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8936                                   struct spoolss_DeletePrinterData *r)
8937 {
8938         struct spoolss_DeletePrinterDataEx r2;
8939
8940         r2.in.handle            = r->in.handle;
8941         r2.in.key_name          = "PrinterDriverData";
8942         r2.in.value_name        = r->in.value_name;
8943
8944         return _spoolss_DeletePrinterDataEx(p, &r2);
8945 }
8946
8947 /****************************************************************
8948  _spoolss_AddForm
8949 ****************************************************************/
8950
8951 WERROR _spoolss_AddForm(struct pipes_struct *p,
8952                         struct spoolss_AddForm *r)
8953 {
8954         struct spoolss_AddFormInfo1 *form;
8955         int snum = -1;
8956         WERROR status = WERR_OK;
8957         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8958         struct dcerpc_binding_handle *b;
8959         TALLOC_CTX *tmp_ctx = NULL;
8960
8961         DEBUG(5,("_spoolss_AddForm\n"));
8962
8963         if (!Printer) {
8964                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8965                         OUR_HANDLE(r->in.handle)));
8966                 return WERR_INVALID_HANDLE;
8967         }
8968
8969         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8970            and not a printer admin, then fail */
8971
8972         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8973             !security_token_has_privilege(p->session_info->security_token,
8974                                           SEC_PRIV_PRINT_OPERATOR)) {
8975                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8976                 return WERR_ACCESS_DENIED;
8977         }
8978
8979         if (r->in.info_ctr->level != 1) {
8980                 return WERR_INVALID_LEVEL;
8981         }
8982
8983         form = r->in.info_ctr->info.info1;
8984         if (!form) {
8985                 return WERR_INVALID_PARAMETER;
8986         }
8987
8988         switch (form->flags) {
8989         case SPOOLSS_FORM_USER:
8990         case SPOOLSS_FORM_BUILTIN:
8991         case SPOOLSS_FORM_PRINTER:
8992                 break;
8993         default:
8994                 return WERR_INVALID_PARAMETER;
8995         }
8996
8997         tmp_ctx = talloc_new(p->mem_ctx);
8998         if (!tmp_ctx) {
8999                 return WERR_NOT_ENOUGH_MEMORY;
9000         }
9001
9002         status = winreg_printer_binding_handle(tmp_ctx,
9003                                                get_session_info_system(),
9004                                                p->msg_ctx,
9005                                                &b);
9006         if (!W_ERROR_IS_OK(status)) {
9007                 goto done;
9008         }
9009
9010         status = winreg_printer_addform1(tmp_ctx, b, form);
9011         if (!W_ERROR_IS_OK(status)) {
9012                 goto done;
9013         }
9014
9015         /*
9016          * ChangeID must always be set if this is a printer
9017          */
9018         if (Printer->printer_type == SPLHND_PRINTER) {
9019                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9020                         status = WERR_INVALID_HANDLE;
9021                         goto done;
9022                 }
9023
9024                 status = winreg_printer_update_changeid(tmp_ctx, b,
9025                                                         lp_const_servicename(snum));
9026         }
9027
9028 done:
9029         talloc_free(tmp_ctx);
9030         return status;
9031 }
9032
9033 /****************************************************************
9034  _spoolss_DeleteForm
9035 ****************************************************************/
9036
9037 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
9038                            struct spoolss_DeleteForm *r)
9039 {
9040         const char *form_name = r->in.form_name;
9041         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9042         int snum = -1;
9043         WERROR status = WERR_OK;
9044         struct dcerpc_binding_handle *b;
9045         TALLOC_CTX *tmp_ctx = NULL;
9046
9047         DEBUG(5,("_spoolss_DeleteForm\n"));
9048
9049         if (!Printer) {
9050                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
9051                         OUR_HANDLE(r->in.handle)));
9052                 return WERR_INVALID_HANDLE;
9053         }
9054
9055         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9056             !security_token_has_privilege(p->session_info->security_token,
9057                                           SEC_PRIV_PRINT_OPERATOR)) {
9058                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
9059                 return WERR_ACCESS_DENIED;
9060         }
9061
9062         tmp_ctx = talloc_new(p->mem_ctx);
9063         if (!tmp_ctx) {
9064                 return WERR_NOT_ENOUGH_MEMORY;
9065         }
9066
9067         status = winreg_printer_binding_handle(tmp_ctx,
9068                                                get_session_info_system(),
9069                                                p->msg_ctx,
9070                                                &b);
9071         if (!W_ERROR_IS_OK(status)) {
9072                 goto done;
9073         }
9074
9075         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
9076         if (!W_ERROR_IS_OK(status)) {
9077                 goto done;
9078         }
9079
9080         /*
9081          * ChangeID must always be set if this is a printer
9082          */
9083         if (Printer->printer_type == SPLHND_PRINTER) {
9084                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9085                         status = WERR_INVALID_HANDLE;
9086                         goto done;
9087                 }
9088
9089                 status = winreg_printer_update_changeid(tmp_ctx, b,
9090                                                         lp_const_servicename(snum));
9091         }
9092
9093 done:
9094         talloc_free(tmp_ctx);
9095         return status;
9096 }
9097
9098 /****************************************************************
9099  _spoolss_SetForm
9100 ****************************************************************/
9101
9102 WERROR _spoolss_SetForm(struct pipes_struct *p,
9103                         struct spoolss_SetForm *r)
9104 {
9105         struct spoolss_AddFormInfo1 *form;
9106         const char *form_name = r->in.form_name;
9107         int snum = -1;
9108         WERROR status = WERR_OK;
9109         struct dcerpc_binding_handle *b;
9110         TALLOC_CTX *tmp_ctx = NULL;
9111
9112         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9113
9114         DEBUG(5,("_spoolss_SetForm\n"));
9115
9116         if (!Printer) {
9117                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
9118                         OUR_HANDLE(r->in.handle)));
9119                 return WERR_INVALID_HANDLE;
9120         }
9121
9122         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9123            and not a printer admin, then fail */
9124
9125         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9126              !security_token_has_privilege(p->session_info->security_token,
9127                                            SEC_PRIV_PRINT_OPERATOR)) {
9128                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
9129                 return WERR_ACCESS_DENIED;
9130         }
9131
9132         if (r->in.info_ctr->level != 1) {
9133                 return WERR_INVALID_LEVEL;
9134         }
9135
9136         form = r->in.info_ctr->info.info1;
9137         if (!form) {
9138                 return WERR_INVALID_PARAMETER;
9139         }
9140
9141         tmp_ctx = talloc_new(p->mem_ctx);
9142         if (!tmp_ctx) {
9143                 return WERR_NOT_ENOUGH_MEMORY;
9144         }
9145
9146         status = winreg_printer_binding_handle(tmp_ctx,
9147                                                get_session_info_system(),
9148                                                p->msg_ctx,
9149                                                &b);
9150         if (!W_ERROR_IS_OK(status)) {
9151                 goto done;
9152         }
9153
9154         status = winreg_printer_setform1(tmp_ctx, b,
9155                                          form_name,
9156                                          form);
9157         if (!W_ERROR_IS_OK(status)) {
9158                 goto done;
9159         }
9160
9161         /*
9162          * ChangeID must always be set if this is a printer
9163          */
9164         if (Printer->printer_type == SPLHND_PRINTER) {
9165                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9166                         status = WERR_INVALID_HANDLE;
9167                         goto done;
9168                 }
9169
9170                 status = winreg_printer_update_changeid(tmp_ctx, b,
9171                                                         lp_const_servicename(snum));
9172         }
9173
9174 done:
9175         talloc_free(tmp_ctx);
9176         return status;
9177 }
9178
9179 /****************************************************************************
9180  fill_print_processor1
9181 ****************************************************************************/
9182
9183 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9184                                     struct spoolss_PrintProcessorInfo1 *r,
9185                                     const char *print_processor_name)
9186 {
9187         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9188         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9189
9190         return WERR_OK;
9191 }
9192
9193 /****************************************************************************
9194  enumprintprocessors level 1.
9195 ****************************************************************************/
9196
9197 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9198                                           union spoolss_PrintProcessorInfo **info_p,
9199                                           uint32_t *count)
9200 {
9201         union spoolss_PrintProcessorInfo *info;
9202         WERROR result;
9203
9204         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9205         W_ERROR_HAVE_NO_MEMORY(info);
9206
9207         *count = 1;
9208
9209         result = fill_print_processor1(info, &info[0].info1, "winprint");
9210         if (!W_ERROR_IS_OK(result)) {
9211                 goto out;
9212         }
9213
9214  out:
9215         if (!W_ERROR_IS_OK(result)) {
9216                 TALLOC_FREE(info);
9217                 *count = 0;
9218                 return result;
9219         }
9220
9221         *info_p = info;
9222
9223         return WERR_OK;
9224 }
9225
9226 /****************************************************************
9227  _spoolss_EnumPrintProcessors
9228 ****************************************************************/
9229
9230 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9231                                     struct spoolss_EnumPrintProcessors *r)
9232 {
9233         WERROR result;
9234
9235         /* that's an [in out] buffer */
9236
9237         if (!r->in.buffer && (r->in.offered != 0)) {
9238                 return WERR_INVALID_PARAMETER;
9239         }
9240
9241         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9242
9243         /*
9244          * Enumerate the print processors ...
9245          *
9246          * Just reply with "winprint", to keep NT happy
9247          * and I can use my nice printer checker.
9248          */
9249
9250         *r->out.count = 0;
9251         *r->out.needed = 0;
9252         *r->out.info = NULL;
9253
9254         if (!get_short_archi(r->in.environment)) {
9255                 return WERR_INVALID_ENVIRONMENT;
9256         }
9257
9258         switch (r->in.level) {
9259         case 1:
9260                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9261                                                      r->out.count);
9262                 break;
9263         default:
9264                 return WERR_INVALID_LEVEL;
9265         }
9266
9267         if (!W_ERROR_IS_OK(result)) {
9268                 return result;
9269         }
9270
9271         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9272                                                      spoolss_EnumPrintProcessors,
9273                                                      *r->out.info, r->in.level,
9274                                                      *r->out.count);
9275         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9276         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9277
9278         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9279 }
9280
9281 /****************************************************************************
9282  fill_printprocdatatype1
9283 ****************************************************************************/
9284
9285 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9286                                       struct spoolss_PrintProcDataTypesInfo1 *r,
9287                                       const char *name_array)
9288 {
9289         r->name_array = talloc_strdup(mem_ctx, name_array);
9290         W_ERROR_HAVE_NO_MEMORY(r->name_array);
9291
9292         return WERR_OK;
9293 }
9294
9295 /****************************************************************************
9296  enumprintprocdatatypes level 1.
9297 ****************************************************************************/
9298
9299 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9300                                              union spoolss_PrintProcDataTypesInfo **info_p,
9301                                              uint32_t *count)
9302 {
9303         WERROR result;
9304         union spoolss_PrintProcDataTypesInfo *info;
9305
9306         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9307         W_ERROR_HAVE_NO_MEMORY(info);
9308
9309         *count = 1;
9310
9311         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9312         if (!W_ERROR_IS_OK(result)) {
9313                 goto out;
9314         }
9315
9316  out:
9317         if (!W_ERROR_IS_OK(result)) {
9318                 TALLOC_FREE(info);
9319                 *count = 0;
9320                 return result;
9321         }
9322
9323         *info_p = info;
9324
9325         return WERR_OK;
9326 }
9327
9328 /****************************************************************
9329  _spoolss_EnumPrintProcessorDataTypes
9330 ****************************************************************/
9331
9332 WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
9333                                             struct spoolss_EnumPrintProcessorDataTypes *r)
9334 {
9335         WERROR result;
9336
9337         /* that's an [in out] buffer */
9338
9339         if (!r->in.buffer && (r->in.offered != 0)) {
9340                 return WERR_INVALID_PARAMETER;
9341         }
9342
9343         DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
9344
9345         *r->out.count = 0;
9346         *r->out.needed = 0;
9347         *r->out.info = NULL;
9348
9349         if (r->in.print_processor_name == NULL ||
9350             !strequal(r->in.print_processor_name, "winprint")) {
9351                 return WERR_UNKNOWN_PRINTPROCESSOR;
9352         }
9353
9354         switch (r->in.level) {
9355         case 1:
9356                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9357                                                         r->out.count);
9358                 break;
9359         default:
9360                 return WERR_INVALID_LEVEL;
9361         }
9362
9363         if (!W_ERROR_IS_OK(result)) {
9364                 return result;
9365         }
9366
9367         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9368                                                      spoolss_EnumPrintProcessorDataTypes,
9369                                                      *r->out.info, r->in.level,
9370                                                      *r->out.count);
9371         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9372         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9373
9374         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9375 }
9376
9377 /****************************************************************************
9378  fill_monitor_1
9379 ****************************************************************************/
9380
9381 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9382                              struct spoolss_MonitorInfo1 *r,
9383                              const char *monitor_name)
9384 {
9385         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9386         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9387
9388         return WERR_OK;
9389 }
9390
9391 /****************************************************************************
9392  fill_monitor_2
9393 ****************************************************************************/
9394
9395 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9396                              struct spoolss_MonitorInfo2 *r,
9397                              const char *monitor_name,
9398                              const char *environment,
9399                              const char *dll_name)
9400 {
9401         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9402         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9403         r->environment                  = talloc_strdup(mem_ctx, environment);
9404         W_ERROR_HAVE_NO_MEMORY(r->environment);
9405         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9406         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9407
9408         return WERR_OK;
9409 }
9410
9411 /****************************************************************************
9412  enumprintmonitors level 1.
9413 ****************************************************************************/
9414
9415 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9416                                         union spoolss_MonitorInfo **info_p,
9417                                         uint32_t *count)
9418 {
9419         union spoolss_MonitorInfo *info;
9420         WERROR result = WERR_OK;
9421
9422         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9423         W_ERROR_HAVE_NO_MEMORY(info);
9424
9425         *count = 2;
9426
9427         result = fill_monitor_1(info, &info[0].info1,
9428                                 SPL_LOCAL_PORT);
9429         if (!W_ERROR_IS_OK(result)) {
9430                 goto out;
9431         }
9432
9433         result = fill_monitor_1(info, &info[1].info1,
9434                                 SPL_TCPIP_PORT);
9435         if (!W_ERROR_IS_OK(result)) {
9436                 goto out;
9437         }
9438
9439 out:
9440         if (!W_ERROR_IS_OK(result)) {
9441                 TALLOC_FREE(info);
9442                 *count = 0;
9443                 return result;
9444         }
9445
9446         *info_p = info;
9447
9448         return WERR_OK;
9449 }
9450
9451 /****************************************************************************
9452  enumprintmonitors level 2.
9453 ****************************************************************************/
9454
9455 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9456                                         union spoolss_MonitorInfo **info_p,
9457                                         uint32_t *count)
9458 {
9459         union spoolss_MonitorInfo *info;
9460         WERROR result = WERR_OK;
9461
9462         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9463         W_ERROR_HAVE_NO_MEMORY(info);
9464
9465         *count = 2;
9466
9467         result = fill_monitor_2(info, &info[0].info2,
9468                                 SPL_LOCAL_PORT,
9469                                 "Windows NT X86", /* FIXME */
9470                                 "localmon.dll");
9471         if (!W_ERROR_IS_OK(result)) {
9472                 goto out;
9473         }
9474
9475         result = fill_monitor_2(info, &info[1].info2,
9476                                 SPL_TCPIP_PORT,
9477                                 "Windows NT X86", /* FIXME */
9478                                 "tcpmon.dll");
9479         if (!W_ERROR_IS_OK(result)) {
9480                 goto out;
9481         }
9482
9483 out:
9484         if (!W_ERROR_IS_OK(result)) {
9485                 TALLOC_FREE(info);
9486                 *count = 0;
9487                 return result;
9488         }
9489
9490         *info_p = info;
9491
9492         return WERR_OK;
9493 }
9494
9495 /****************************************************************
9496  _spoolss_EnumMonitors
9497 ****************************************************************/
9498
9499 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9500                              struct spoolss_EnumMonitors *r)
9501 {
9502         WERROR result;
9503
9504         /* that's an [in out] buffer */
9505
9506         if (!r->in.buffer && (r->in.offered != 0)) {
9507                 return WERR_INVALID_PARAMETER;
9508         }
9509
9510         DEBUG(5,("_spoolss_EnumMonitors\n"));
9511
9512         /*
9513          * Enumerate the print monitors ...
9514          *
9515          * Just reply with "Local Port", to keep NT happy
9516          * and I can use my nice printer checker.
9517          */
9518
9519         *r->out.count = 0;
9520         *r->out.needed = 0;
9521         *r->out.info = NULL;
9522
9523         switch (r->in.level) {
9524         case 1:
9525                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9526                                                    r->out.count);
9527                 break;
9528         case 2:
9529                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9530                                                    r->out.count);
9531                 break;
9532         default:
9533                 return WERR_INVALID_LEVEL;
9534         }
9535
9536         if (!W_ERROR_IS_OK(result)) {
9537                 return result;
9538         }
9539
9540         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9541                                                      spoolss_EnumMonitors,
9542                                                      *r->out.info, r->in.level,
9543                                                      *r->out.count);
9544         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9545         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9546
9547         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9548 }
9549
9550 /****************************************************************************
9551 ****************************************************************************/
9552
9553 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9554                              const print_queue_struct *queue,
9555                              int count, int snum,
9556                              struct spoolss_PrinterInfo2 *pinfo2,
9557                              uint32_t jobid,
9558                              int sysjob,
9559                              struct spoolss_JobInfo1 *r)
9560 {
9561         int i = 0;
9562         bool found = false;
9563
9564         for (i=0; i<count; i++) {
9565                 if (queue[i].sysjob == sysjob) {
9566                         found = true;
9567                         break;
9568                 }
9569         }
9570
9571         if (found == false) {
9572                 /* NT treats not found as bad param... yet another bad choice */
9573                 return WERR_INVALID_PARAMETER;
9574         }
9575
9576         return fill_job_info1(mem_ctx,
9577                               r,
9578                               &queue[i],
9579                               jobid,
9580                               i,
9581                               snum,
9582                               pinfo2);
9583 }
9584
9585 /****************************************************************************
9586 ****************************************************************************/
9587
9588 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9589                              const print_queue_struct *queue,
9590                              int count, int snum,
9591                              struct spoolss_PrinterInfo2 *pinfo2,
9592                              uint32_t jobid,
9593                              int sysjob,
9594                              struct spoolss_JobInfo2 *r)
9595 {
9596         int i = 0;
9597         bool found = false;
9598         struct spoolss_DeviceMode *devmode;
9599         WERROR result;
9600
9601         for (i=0; i<count; i++) {
9602                 if (queue[i].sysjob == sysjob) {
9603                         found = true;
9604                         break;
9605                 }
9606         }
9607
9608         if (found == false) {
9609                 /* NT treats not found as bad param... yet another bad
9610                    choice */
9611                 return WERR_INVALID_PARAMETER;
9612         }
9613
9614         /*
9615          * if the print job does not have a DEVMODE associated with it,
9616          * just use the one for the printer. A NULL devicemode is not
9617          *  a failure condition
9618          */
9619
9620         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9621         if (!devmode) {
9622                 result = spoolss_create_default_devmode(mem_ctx,
9623                                                 pinfo2->printername,
9624                                                 &devmode);
9625                 if (!W_ERROR_IS_OK(result)) {
9626                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9627                         return result;
9628                 }
9629         }
9630
9631         return fill_job_info2(mem_ctx,
9632                               r,
9633                               &queue[i],
9634                               jobid,
9635                               i,
9636                               snum,
9637                               pinfo2,
9638                               devmode);
9639 }
9640
9641 /****************************************************************
9642  _spoolss_GetJob
9643 ****************************************************************/
9644
9645 WERROR _spoolss_GetJob(struct pipes_struct *p,
9646                        struct spoolss_GetJob *r)
9647 {
9648         WERROR result = WERR_OK;
9649         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9650         const char *svc_name;
9651         int sysjob;
9652         int snum;
9653         int count;
9654         struct tdb_print_db *pdb;
9655         print_queue_struct      *queue = NULL;
9656         print_status_struct prt_status;
9657
9658         /* that's an [in out] buffer */
9659
9660         if (!r->in.buffer && (r->in.offered != 0)) {
9661                 result = WERR_INVALID_PARAMETER;
9662                 goto err_jinfo_free;
9663         }
9664
9665         DEBUG(5,("_spoolss_GetJob\n"));
9666
9667         *r->out.needed = 0;
9668
9669         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9670                 result = WERR_INVALID_HANDLE;
9671                 goto err_jinfo_free;
9672         }
9673
9674         svc_name = lp_const_servicename(snum);
9675         if (svc_name == NULL) {
9676                 result = WERR_INVALID_PARAMETER;
9677                 goto err_jinfo_free;
9678         }
9679
9680         result = winreg_get_printer_internal(p->mem_ctx,
9681                                     get_session_info_system(),
9682                                     p->msg_ctx,
9683                                     svc_name,
9684                                     &pinfo2);
9685         if (!W_ERROR_IS_OK(result)) {
9686                 goto err_jinfo_free;
9687         }
9688
9689         pdb = get_print_db_byname(svc_name);
9690         if (pdb == NULL) {
9691                 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9692                 result = WERR_INVALID_PARAMETER;
9693                 goto err_pinfo_free;
9694         }
9695
9696         sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9697         release_print_db(pdb);
9698         if (sysjob == -1) {
9699                 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9700                 result = WERR_INVALID_PARAMETER;
9701                 goto err_pinfo_free;
9702         }
9703
9704         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9705
9706         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9707                      count, prt_status.status, prt_status.message));
9708
9709         switch (r->in.level) {
9710         case 1:
9711                 result = getjob_level_1(p->mem_ctx,
9712                                         queue, count, snum, pinfo2,
9713                                         r->in.job_id, sysjob,
9714                                         &r->out.info->info1);
9715                 break;
9716         case 2:
9717                 result = getjob_level_2(p->mem_ctx,
9718                                         queue, count, snum, pinfo2,
9719                                         r->in.job_id, sysjob,
9720                                         &r->out.info->info2);
9721                 break;
9722         default:
9723                 result = WERR_INVALID_LEVEL;
9724                 break;
9725         }
9726
9727         SAFE_FREE(queue);
9728         TALLOC_FREE(pinfo2);
9729
9730         if (!W_ERROR_IS_OK(result)) {
9731                 goto err_jinfo_free;
9732         }
9733
9734         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9735                                                                                    r->in.level);
9736         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9737
9738         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9739
9740 err_pinfo_free:
9741         TALLOC_FREE(pinfo2);
9742 err_jinfo_free:
9743         TALLOC_FREE(r->out.info);
9744         return result;
9745 }
9746
9747 /****************************************************************
9748  _spoolss_GetPrinterDataEx
9749 ****************************************************************/
9750
9751 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9752                                  struct spoolss_GetPrinterDataEx *r)
9753 {
9754
9755         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9756         const char *printer;
9757         int                     snum = 0;
9758         WERROR result = WERR_OK;
9759         DATA_BLOB blob;
9760         enum winreg_Type val_type = REG_NONE;
9761         uint8_t *val_data = NULL;
9762         uint32_t val_size = 0;
9763         struct dcerpc_binding_handle *b;
9764         TALLOC_CTX *tmp_ctx;
9765
9766         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9767
9768         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9769                 r->in.key_name, r->in.value_name));
9770
9771         /* in case of problem, return some default values */
9772
9773         *r->out.needed  = 0;
9774         *r->out.type    = REG_NONE;
9775
9776         tmp_ctx = talloc_new(p->mem_ctx);
9777         if (!tmp_ctx) {
9778                 return WERR_NOT_ENOUGH_MEMORY;
9779         }
9780
9781         if (!Printer) {
9782                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9783                         OUR_HANDLE(r->in.handle)));
9784                 result = WERR_INVALID_HANDLE;
9785                 goto done;
9786         }
9787
9788         /* Is the handle to a printer or to the server? */
9789
9790         if (Printer->printer_type == SPLHND_SERVER) {
9791
9792                 union spoolss_PrinterData data;
9793
9794                 result = getprinterdata_printer_server(tmp_ctx,
9795                                                        r->in.value_name,
9796                                                        r->out.type,
9797                                                        &data);
9798                 if (!W_ERROR_IS_OK(result)) {
9799                         goto done;
9800                 }
9801
9802                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9803                                                   *r->out.type, &data);
9804                 if (!W_ERROR_IS_OK(result)) {
9805                         goto done;
9806                 }
9807
9808                 *r->out.needed = blob.length;
9809
9810                 if (r->in.offered >= *r->out.needed) {
9811                         memcpy(r->out.data, blob.data, blob.length);
9812                 }
9813
9814                 result = WERR_OK;
9815                 goto done;
9816         }
9817
9818         /* check to see if the keyname is valid */
9819         if (!strlen(r->in.key_name)) {
9820                 result = WERR_INVALID_PARAMETER;
9821                 goto done;
9822         }
9823
9824         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9825                 result = WERR_INVALID_HANDLE;
9826                 goto done;
9827         }
9828         printer = lp_const_servicename(snum);
9829
9830         result = winreg_printer_binding_handle(tmp_ctx,
9831                                                get_session_info_system(),
9832                                                p->msg_ctx,
9833                                                &b);
9834         if (!W_ERROR_IS_OK(result)) {
9835                 goto done;
9836         }
9837
9838         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9839         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9840             strequal(r->in.value_name, "ChangeId")) {
9841                 *r->out.type = REG_DWORD;
9842                 *r->out.needed = 4;
9843                 if (r->in.offered >= *r->out.needed) {
9844                         uint32_t changeid = 0;
9845
9846                         result = winreg_printer_get_changeid(tmp_ctx, b,
9847                                                              printer,
9848                                                              &changeid);
9849                         if (!W_ERROR_IS_OK(result)) {
9850                                 goto done;
9851                         }
9852
9853                         SIVAL(r->out.data, 0, changeid);
9854                         result = WERR_OK;
9855                 }
9856                 goto done;
9857         }
9858
9859         result = winreg_get_printer_dataex(tmp_ctx, b,
9860                                            printer,
9861                                            r->in.key_name,
9862                                            r->in.value_name,
9863                                            &val_type,
9864                                            &val_data,
9865                                            &val_size);
9866         if (!W_ERROR_IS_OK(result)) {
9867                 goto done;
9868         }
9869
9870         *r->out.needed = val_size;
9871         *r->out.type = val_type;
9872
9873         if (r->in.offered >= *r->out.needed) {
9874                 memcpy(r->out.data, val_data, val_size);
9875         }
9876
9877 done:
9878         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9879
9880         if (W_ERROR_IS_OK(result)) {
9881                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9882         }
9883
9884         talloc_free(tmp_ctx);
9885         return result;
9886 }
9887
9888 /****************************************************************
9889  _spoolss_SetPrinterDataEx
9890 ****************************************************************/
9891
9892 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9893                                  struct spoolss_SetPrinterDataEx *r)
9894 {
9895         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9896         int                     snum = 0;
9897         WERROR                  result = WERR_OK;
9898         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9899         char                    *oid_string;
9900         struct dcerpc_binding_handle *b;
9901         TALLOC_CTX *tmp_ctx;
9902
9903         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9904
9905         /* From MSDN documentation of SetPrinterDataEx: pass request to
9906            SetPrinterData if key is "PrinterDriverData" */
9907
9908         if (!Printer) {
9909                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9910                         OUR_HANDLE(r->in.handle)));
9911                 return WERR_INVALID_HANDLE;
9912         }
9913
9914         if (Printer->printer_type == SPLHND_SERVER) {
9915                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9916                         "Not implemented for server handles yet\n"));
9917                 return WERR_INVALID_PARAMETER;
9918         }
9919
9920         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9921                 return WERR_INVALID_HANDLE;
9922         }
9923
9924         /*
9925          * Access check : NT returns "access denied" if you make a
9926          * SetPrinterData call without the necessary privildge.
9927          * we were originally returning OK if nothing changed
9928          * which made Win2k issue **a lot** of SetPrinterData
9929          * when connecting to a printer  --jerry
9930          */
9931
9932         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9933                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9934                         "change denied by handle access permissions\n"));
9935                 return WERR_ACCESS_DENIED;
9936         }
9937
9938         tmp_ctx = talloc_new(p->mem_ctx);
9939         if (!tmp_ctx) {
9940                 return WERR_NOT_ENOUGH_MEMORY;
9941         }
9942
9943         result = winreg_printer_binding_handle(tmp_ctx,
9944                                                get_session_info_system(),
9945                                                p->msg_ctx,
9946                                                &b);
9947         if (!W_ERROR_IS_OK(result)) {
9948                 goto done;
9949         }
9950
9951         result = winreg_get_printer(tmp_ctx, b,
9952                                     lp_servicename(talloc_tos(), snum),
9953                                     &pinfo2);
9954         if (!W_ERROR_IS_OK(result)) {
9955                 goto done;
9956         }
9957
9958         /* check for OID in valuename */
9959
9960         oid_string = strchr(r->in.value_name, ',');
9961         if (oid_string) {
9962                 *oid_string = '\0';
9963                 oid_string++;
9964         }
9965
9966         /* save the registry data */
9967
9968         result = winreg_set_printer_dataex(tmp_ctx, b,
9969                                            pinfo2->sharename,
9970                                            r->in.key_name,
9971                                            r->in.value_name,
9972                                            r->in.type,
9973                                            r->in.data,
9974                                            r->in.offered);
9975
9976         if (W_ERROR_IS_OK(result)) {
9977                 /* save the OID if one was specified */
9978                 if (oid_string) {
9979                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9980                                 r->in.key_name, SPOOL_OID_KEY);
9981                         if (!str) {
9982                                 result = WERR_NOT_ENOUGH_MEMORY;
9983                                 goto done;
9984                         }
9985
9986                         /*
9987                          * I'm not checking the status here on purpose.  Don't know
9988                          * if this is right, but I'm returning the status from the
9989                          * previous set_printer_dataex() call.  I have no idea if
9990                          * this is right.    --jerry
9991                          */
9992                         winreg_set_printer_dataex(tmp_ctx, b,
9993                                                   pinfo2->sharename,
9994                                                   str,
9995                                                   r->in.value_name,
9996                                                   REG_SZ,
9997                                                   (uint8_t *) oid_string,
9998                                                   strlen(oid_string) + 1);
9999                 }
10000
10001                 result = winreg_printer_update_changeid(tmp_ctx, b,
10002                                                         lp_const_servicename(snum));
10003
10004         }
10005
10006 done:
10007         talloc_free(tmp_ctx);
10008         return result;
10009 }
10010
10011 /****************************************************************
10012  _spoolss_DeletePrinterDataEx
10013 ****************************************************************/
10014
10015 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
10016                                     struct spoolss_DeletePrinterDataEx *r)
10017 {
10018         const char *printer;
10019         int             snum=0;
10020         WERROR          status = WERR_OK;
10021         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10022
10023         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
10024
10025         if (!Printer) {
10026                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
10027                         "Invalid handle (%s:%u:%u).\n",
10028                         OUR_HANDLE(r->in.handle)));
10029                 return WERR_INVALID_HANDLE;
10030         }
10031
10032         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10033                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
10034                         "printer properties change denied by handle\n"));
10035                 return WERR_ACCESS_DENIED;
10036         }
10037
10038         if (!r->in.value_name || !r->in.key_name) {
10039                 return WERR_NOT_ENOUGH_MEMORY;
10040         }
10041
10042         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10043                 return WERR_INVALID_HANDLE;
10044         }
10045         printer = lp_const_servicename(snum);
10046
10047         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
10048                                               get_session_info_system(),
10049                                               p->msg_ctx,
10050                                               printer,
10051                                               r->in.key_name,
10052                                               r->in.value_name);
10053         if (W_ERROR_IS_OK(status)) {
10054                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
10055                                                         get_session_info_system(),
10056                                                         p->msg_ctx,
10057                                                         printer);
10058         }
10059
10060         return status;
10061 }
10062
10063 /****************************************************************
10064  _spoolss_EnumPrinterKey
10065 ****************************************************************/
10066
10067 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
10068                                struct spoolss_EnumPrinterKey *r)
10069 {
10070         uint32_t        num_keys;
10071         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10072         int             snum = 0;
10073         WERROR          result = WERR_FILE_NOT_FOUND;
10074         const char **array = NULL;
10075         DATA_BLOB blob;
10076
10077         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
10078
10079         if (!Printer) {
10080                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
10081                         OUR_HANDLE(r->in.handle)));
10082                 return WERR_INVALID_HANDLE;
10083         }
10084
10085         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10086                 return WERR_INVALID_HANDLE;
10087         }
10088
10089         result = winreg_enum_printer_key_internal(p->mem_ctx,
10090                                          get_session_info_system(),
10091                                          p->msg_ctx,
10092                                          lp_const_servicename(snum),
10093                                          r->in.key_name,
10094                                          &num_keys,
10095                                          &array);
10096         if (!W_ERROR_IS_OK(result)) {
10097                 goto done;
10098         }
10099
10100         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
10101                 result = WERR_NOT_ENOUGH_MEMORY;
10102                 goto done;
10103         }
10104
10105         *r->out._ndr_size = r->in.offered / 2;
10106         *r->out.needed = blob.length;
10107
10108         if (r->in.offered < *r->out.needed) {
10109                 result = WERR_MORE_DATA;
10110         } else {
10111                 result = WERR_OK;
10112                 r->out.key_buffer->string_array = array;
10113         }
10114
10115  done:
10116         if (!W_ERROR_IS_OK(result)) {
10117                 TALLOC_FREE(array);
10118                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
10119                         *r->out.needed = 0;
10120                 }
10121         }
10122
10123         return result;
10124 }
10125
10126 /****************************************************************
10127  _spoolss_DeletePrinterKey
10128 ****************************************************************/
10129
10130 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
10131                                  struct spoolss_DeletePrinterKey *r)
10132 {
10133         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10134         int                     snum=0;
10135         WERROR                  status;
10136         const char *printer;
10137         struct dcerpc_binding_handle *b;
10138         TALLOC_CTX *tmp_ctx;
10139
10140         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10141
10142         if (!Printer) {
10143                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10144                         OUR_HANDLE(r->in.handle)));
10145                 return WERR_INVALID_HANDLE;
10146         }
10147
10148         /* if keyname == NULL, return error */
10149         if ( !r->in.key_name )
10150                 return WERR_INVALID_PARAMETER;
10151
10152         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10153                 return WERR_INVALID_HANDLE;
10154         }
10155
10156         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10157                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
10158                         "printer properties change denied by handle\n"));
10159                 return WERR_ACCESS_DENIED;
10160         }
10161
10162         printer = lp_const_servicename(snum);
10163
10164         tmp_ctx = talloc_new(p->mem_ctx);
10165         if (!tmp_ctx) {
10166                 return WERR_NOT_ENOUGH_MEMORY;
10167         }
10168
10169         status = winreg_printer_binding_handle(tmp_ctx,
10170                                                get_session_info_system(),
10171                                                p->msg_ctx,
10172                                                &b);
10173         if (!W_ERROR_IS_OK(status)) {
10174                 goto done;
10175         }
10176
10177         /* delete the key and all subkeys */
10178         status = winreg_delete_printer_key(tmp_ctx, b,
10179                                            printer,
10180                                            r->in.key_name);
10181         if (W_ERROR_IS_OK(status)) {
10182                 status = winreg_printer_update_changeid(tmp_ctx, b,
10183                                                         printer);
10184         }
10185
10186 done:
10187         talloc_free(tmp_ctx);
10188         return status;
10189 }
10190
10191 /****************************************************************
10192  _spoolss_EnumPrinterDataEx
10193 ****************************************************************/
10194
10195 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10196                                   struct spoolss_EnumPrinterDataEx *r)
10197 {
10198         uint32_t        count = 0;
10199         struct spoolss_PrinterEnumValues *info = NULL;
10200         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10201         int             snum;
10202         WERROR          result;
10203
10204         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10205
10206         *r->out.count = 0;
10207         *r->out.needed = 0;
10208         *r->out.info = NULL;
10209
10210         if (!Printer) {
10211                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10212                         OUR_HANDLE(r->in.handle)));
10213                 return WERR_INVALID_HANDLE;
10214         }
10215
10216         /*
10217          * first check for a keyname of NULL or "".  Win2k seems to send
10218          * this a lot and we should send back WERR_INVALID_PARAMETER
10219          * no need to spend time looking up the printer in this case.
10220          * --jerry
10221          */
10222
10223         if (!strlen(r->in.key_name)) {
10224                 result = WERR_INVALID_PARAMETER;
10225                 goto done;
10226         }
10227
10228         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10229                 return WERR_INVALID_HANDLE;
10230         }
10231
10232         /* now look for a match on the key name */
10233         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10234                                             get_session_info_system(),
10235                                             p->msg_ctx,
10236                                             lp_const_servicename(snum),
10237                                             r->in.key_name,
10238                                             &count,
10239                                             &info);
10240         if (!W_ERROR_IS_OK(result)) {
10241                 goto done;
10242         }
10243
10244 #if 0 /* FIXME - gd */
10245         /* housekeeping information in the reply */
10246
10247         /* Fix from Martin Zielinski <mz@seh.de> - ensure
10248          * the hand marshalled container size is a multiple
10249          * of 4 bytes for RPC alignment.
10250          */
10251
10252         if (needed % 4) {
10253                 needed += 4-(needed % 4);
10254         }
10255 #endif
10256         *r->out.count   = count;
10257         *r->out.info    = info;
10258
10259  done:
10260         if (!W_ERROR_IS_OK(result)) {
10261                 return result;
10262         }
10263
10264         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10265                                                spoolss_EnumPrinterDataEx,
10266                                                *r->out.info,
10267                                                *r->out.count);
10268         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10269         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10270
10271         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10272 }
10273
10274 /****************************************************************************
10275 ****************************************************************************/
10276
10277 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10278                                                  const char *servername,
10279                                                  const char *environment,
10280                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
10281 {
10282         WERROR werr;
10283         char *path = NULL;
10284
10285         werr = compose_spoolss_server_path(mem_ctx,
10286                                            servername,
10287                                            environment,
10288                                            SPOOLSS_PRTPROCS_PATH,
10289                                            &path);
10290         if (!W_ERROR_IS_OK(werr)) {
10291                 return werr;
10292         }
10293
10294         DEBUG(4,("print processor directory: [%s]\n", path));
10295
10296         r->directory_name = path;
10297
10298         return WERR_OK;
10299 }
10300
10301 /****************************************************************
10302  _spoolss_GetPrintProcessorDirectory
10303 ****************************************************************/
10304
10305 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10306                                            struct spoolss_GetPrintProcessorDirectory *r)
10307 {
10308         WERROR result;
10309         char *prnproc_share = NULL;
10310         bool prnproc_share_exists = false;
10311         int snum;
10312
10313         /* that's an [in out] buffer */
10314
10315         if (!r->in.buffer && (r->in.offered != 0)) {
10316                 result = WERR_INVALID_PARAMETER;
10317                 goto err_info_free;
10318         }
10319
10320         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10321                 r->in.level));
10322
10323         *r->out.needed = 0;
10324
10325         /* r->in.level is ignored */
10326
10327         /* We always should reply with a local print processor directory so that
10328          * users are not forced to have a [prnproc$] share on the Samba spoolss
10329          * server, if users decide to do so, lets announce it though - Guenther */
10330
10331         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10332         if (!prnproc_share) {
10333                 result = WERR_NOT_ENOUGH_MEMORY;
10334                 goto err_info_free;
10335         }
10336         if (snum != -1) {
10337                 prnproc_share_exists = true;
10338         }
10339
10340         result = getprintprocessordirectory_level_1(p->mem_ctx,
10341                                                     prnproc_share_exists ? r->in.server : NULL,
10342                                                     r->in.environment,
10343                                                     &r->out.info->info1);
10344         if (!W_ERROR_IS_OK(result)) {
10345                 goto err_info_free;
10346         }
10347
10348         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10349                                                                                    r->out.info, r->in.level);
10350         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10351
10352         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10353
10354 err_info_free:
10355         TALLOC_FREE(r->out.info);
10356         return result;
10357 }
10358
10359 /*******************************************************************
10360  ********************************************************************/
10361
10362 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10363                                const char *dllname)
10364 {
10365         enum ndr_err_code ndr_err;
10366         struct spoolss_MonitorUi ui;
10367
10368         ui.dll_name = dllname;
10369
10370         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10371                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10372         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10373                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10374         }
10375         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10376 }
10377
10378 /*******************************************************************
10379  Streams the monitor UI DLL name in UNICODE
10380 *******************************************************************/
10381
10382 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10383                                struct security_token *token, DATA_BLOB *in,
10384                                DATA_BLOB *out, uint32_t *needed)
10385 {
10386         const char *dllname = "tcpmonui.dll";
10387
10388         *needed = (strlen(dllname)+1) * 2;
10389
10390         if (out->length < *needed) {
10391                 return WERR_INSUFFICIENT_BUFFER;
10392         }
10393
10394         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10395                 return WERR_NOT_ENOUGH_MEMORY;
10396         }
10397
10398         return WERR_OK;
10399 }
10400
10401 /*******************************************************************
10402  ********************************************************************/
10403
10404 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10405                              struct spoolss_PortData1 *port1,
10406                              const DATA_BLOB *buf)
10407 {
10408         enum ndr_err_code ndr_err;
10409         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10410                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10411         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10412                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10413         }
10414         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10415 }
10416
10417 /*******************************************************************
10418  ********************************************************************/
10419
10420 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10421                              struct spoolss_PortData2 *port2,
10422                              const DATA_BLOB *buf)
10423 {
10424         enum ndr_err_code ndr_err;
10425         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10426                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10427         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10428                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10429         }
10430         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10431 }
10432
10433 /*******************************************************************
10434  Create a new TCP/IP port
10435 *******************************************************************/
10436
10437 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10438                              struct security_token *token, DATA_BLOB *in,
10439                              DATA_BLOB *out, uint32_t *needed)
10440 {
10441         struct spoolss_PortData1 port1;
10442         struct spoolss_PortData2 port2;
10443         char *device_uri = NULL;
10444         uint32_t version;
10445
10446         const char *portname;
10447         const char *hostaddress;
10448         const char *queue;
10449         uint32_t port_number;
10450         uint32_t protocol;
10451
10452         /* peek for spoolss_PortData version */
10453
10454         if (!in || (in->length < (128 + 4))) {
10455                 return WERR_GEN_FAILURE;
10456         }
10457
10458         version = IVAL(in->data, 128);
10459
10460         switch (version) {
10461                 case 1:
10462                         ZERO_STRUCT(port1);
10463
10464                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10465                                 return WERR_NOT_ENOUGH_MEMORY;
10466                         }
10467
10468                         portname        = port1.portname;
10469                         hostaddress     = port1.hostaddress;
10470                         queue           = port1.queue;
10471                         protocol        = port1.protocol;
10472                         port_number     = port1.port_number;
10473
10474                         break;
10475                 case 2:
10476                         ZERO_STRUCT(port2);
10477
10478                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10479                                 return WERR_NOT_ENOUGH_MEMORY;
10480                         }
10481
10482                         portname        = port2.portname;
10483                         hostaddress     = port2.hostaddress;
10484                         queue           = port2.queue;
10485                         protocol        = port2.protocol;
10486                         port_number     = port2.port_number;
10487
10488                         break;
10489                 default:
10490                         DEBUG(1,("xcvtcp_addport: "
10491                                 "unknown version of port_data: %d\n", version));
10492                         return WERR_UNKNOWN_PORT;
10493         }
10494
10495         /* create the device URI and call the add_port_hook() */
10496
10497         switch (protocol) {
10498         case PROTOCOL_RAWTCP_TYPE:
10499                 device_uri = talloc_asprintf(mem_ctx,
10500                                 "socket://%s:%d/", hostaddress,
10501                                 port_number);
10502                 break;
10503
10504         case PROTOCOL_LPR_TYPE:
10505                 device_uri = talloc_asprintf(mem_ctx,
10506                         "lpr://%s/%s", hostaddress, queue );
10507                 break;
10508
10509         default:
10510                 return WERR_UNKNOWN_PORT;
10511         }
10512
10513         if (!device_uri) {
10514                 return WERR_NOT_ENOUGH_MEMORY;
10515         }
10516
10517         return add_port_hook(mem_ctx, token, portname, device_uri);
10518 }
10519
10520 /*******************************************************************
10521 *******************************************************************/
10522
10523 struct xcv_api_table xcvtcp_cmds[] = {
10524         { "MonitorUI",  xcvtcp_monitorui },
10525         { "AddPort",    xcvtcp_addport},
10526         { NULL,         NULL }
10527 };
10528
10529 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10530                                      struct security_token *token, const char *command,
10531                                      DATA_BLOB *inbuf,
10532                                      DATA_BLOB *outbuf,
10533                                      uint32_t *needed )
10534 {
10535         int i;
10536
10537         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10538
10539         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10540                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10541                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10542         }
10543
10544         return WERR_INVALID_FUNCTION;
10545 }
10546
10547 /*******************************************************************
10548 *******************************************************************/
10549 #if 0   /* don't support management using the "Local Port" monitor */
10550
10551 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10552                                  struct security_token *token, DATA_BLOB *in,
10553                                  DATA_BLOB *out, uint32_t *needed)
10554 {
10555         const char *dllname = "localui.dll";
10556
10557         *needed = (strlen(dllname)+1) * 2;
10558
10559         if (out->length < *needed) {
10560                 return WERR_INSUFFICIENT_BUFFER;
10561         }
10562
10563         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10564                 return WERR_NOT_ENOUGH_MEMORY;
10565         }
10566
10567         return WERR_OK;
10568 }
10569
10570 /*******************************************************************
10571 *******************************************************************/
10572
10573 struct xcv_api_table xcvlocal_cmds[] = {
10574         { "MonitorUI",  xcvlocal_monitorui },
10575         { NULL,         NULL }
10576 };
10577 #else
10578 struct xcv_api_table xcvlocal_cmds[] = {
10579         { NULL,         NULL }
10580 };
10581 #endif
10582
10583
10584
10585 /*******************************************************************
10586 *******************************************************************/
10587
10588 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10589                                        struct security_token *token, const char *command,
10590                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10591                                        uint32_t *needed)
10592 {
10593         int i;
10594
10595         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10596
10597         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10598                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10599                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10600         }
10601         return WERR_INVALID_FUNCTION;
10602 }
10603
10604 /****************************************************************
10605  _spoolss_XcvData
10606 ****************************************************************/
10607
10608 WERROR _spoolss_XcvData(struct pipes_struct *p,
10609                         struct spoolss_XcvData *r)
10610 {
10611         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10612         DATA_BLOB out_data = data_blob_null;
10613         WERROR werror;
10614
10615         if (!Printer) {
10616                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10617                         OUR_HANDLE(r->in.handle)));
10618                 return WERR_INVALID_HANDLE;
10619         }
10620
10621         /* Has to be a handle to the TCP/IP port monitor */
10622
10623         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10624                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10625                 return WERR_INVALID_HANDLE;
10626         }
10627
10628         /* requires administrative access to the server */
10629
10630         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10631                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10632                 return WERR_ACCESS_DENIED;
10633         }
10634
10635         /* Allocate the outgoing buffer */
10636
10637         if (r->in.out_data_size) {
10638                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10639                 if (out_data.data == NULL) {
10640                         return WERR_NOT_ENOUGH_MEMORY;
10641                 }
10642         }
10643
10644         switch ( Printer->printer_type ) {
10645         case SPLHND_PORTMON_TCP:
10646                 werror = process_xcvtcp_command(p->mem_ctx,
10647                                                 p->session_info->security_token,
10648                                                 r->in.function_name,
10649                                                 &r->in.in_data, &out_data,
10650                                                 r->out.needed);
10651                 break;
10652         case SPLHND_PORTMON_LOCAL:
10653                 werror = process_xcvlocal_command(p->mem_ctx,
10654                                                   p->session_info->security_token,
10655                                                   r->in.function_name,
10656                                                   &r->in.in_data, &out_data,
10657                                                   r->out.needed);
10658                 break;
10659         default:
10660                 werror = WERR_INVALID_PRINT_MONITOR;
10661         }
10662
10663         if (!W_ERROR_IS_OK(werror)) {
10664                 return werror;
10665         }
10666
10667         *r->out.status_code = 0;
10668
10669         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10670                 memcpy(r->out.out_data, out_data.data,
10671                         MIN(r->in.out_data_size, out_data.length));
10672         }
10673
10674         return WERR_OK;
10675 }
10676
10677 /****************************************************************
10678  _spoolss_AddPrintProcessor
10679 ****************************************************************/
10680
10681 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10682                                   struct spoolss_AddPrintProcessor *r)
10683 {
10684         /* for now, just indicate success and ignore the add.  We'll
10685            automatically set the winprint processor for printer
10686            entries later.  Used to debug the LexMark Optra S 1855 PCL
10687            driver --jerry */
10688
10689         return WERR_OK;
10690 }
10691
10692 /****************************************************************
10693  _spoolss_AddPort
10694 ****************************************************************/
10695
10696 WERROR _spoolss_AddPort(struct pipes_struct *p,
10697                         struct spoolss_AddPort *r)
10698 {
10699         /* do what w2k3 does */
10700
10701         return WERR_NOT_SUPPORTED;
10702 }
10703
10704 /****************************************************************
10705  _spoolss_GetPrinterDriver
10706 ****************************************************************/
10707
10708 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10709                                  struct spoolss_GetPrinterDriver *r)
10710 {
10711         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10712         return WERR_NOT_SUPPORTED;
10713 }
10714
10715 /****************************************************************
10716  _spoolss_ReadPrinter
10717 ****************************************************************/
10718
10719 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10720                             struct spoolss_ReadPrinter *r)
10721 {
10722         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10723         return WERR_NOT_SUPPORTED;
10724 }
10725
10726 /****************************************************************
10727  _spoolss_WaitForPrinterChange
10728 ****************************************************************/
10729
10730 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10731                                      struct spoolss_WaitForPrinterChange *r)
10732 {
10733         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10734         return WERR_NOT_SUPPORTED;
10735 }
10736
10737 /****************************************************************
10738  _spoolss_ConfigurePort
10739 ****************************************************************/
10740
10741 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10742                               struct spoolss_ConfigurePort *r)
10743 {
10744         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10745         return WERR_NOT_SUPPORTED;
10746 }
10747
10748 /****************************************************************
10749  _spoolss_DeletePort
10750 ****************************************************************/
10751
10752 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10753                            struct spoolss_DeletePort *r)
10754 {
10755         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10756         return WERR_NOT_SUPPORTED;
10757 }
10758
10759 /****************************************************************
10760  _spoolss_CreatePrinterIC
10761 ****************************************************************/
10762
10763 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10764                                 struct spoolss_CreatePrinterIC *r)
10765 {
10766         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10767         return WERR_NOT_SUPPORTED;
10768 }
10769
10770 /****************************************************************
10771  _spoolss_PlayGDIScriptOnPrinterIC
10772 ****************************************************************/
10773
10774 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10775                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10776 {
10777         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10778         return WERR_NOT_SUPPORTED;
10779 }
10780
10781 /****************************************************************
10782  _spoolss_DeletePrinterIC
10783 ****************************************************************/
10784
10785 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10786                                 struct spoolss_DeletePrinterIC *r)
10787 {
10788         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10789         return WERR_NOT_SUPPORTED;
10790 }
10791
10792 /****************************************************************
10793  _spoolss_AddPrinterConnection
10794 ****************************************************************/
10795
10796 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10797                                      struct spoolss_AddPrinterConnection *r)
10798 {
10799         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10800         return WERR_NOT_SUPPORTED;
10801 }
10802
10803 /****************************************************************
10804  _spoolss_DeletePrinterConnection
10805 ****************************************************************/
10806
10807 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10808                                         struct spoolss_DeletePrinterConnection *r)
10809 {
10810         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10811         return WERR_NOT_SUPPORTED;
10812 }
10813
10814 /****************************************************************
10815  _spoolss_PrinterMessageBox
10816 ****************************************************************/
10817
10818 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10819                                   struct spoolss_PrinterMessageBox *r)
10820 {
10821         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10822         return WERR_NOT_SUPPORTED;
10823 }
10824
10825 /****************************************************************
10826  _spoolss_AddMonitor
10827 ****************************************************************/
10828
10829 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10830                            struct spoolss_AddMonitor *r)
10831 {
10832         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10833         return WERR_NOT_SUPPORTED;
10834 }
10835
10836 /****************************************************************
10837  _spoolss_DeleteMonitor
10838 ****************************************************************/
10839
10840 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10841                               struct spoolss_DeleteMonitor *r)
10842 {
10843         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10844         return WERR_NOT_SUPPORTED;
10845 }
10846
10847 /****************************************************************
10848  _spoolss_DeletePrintProcessor
10849 ****************************************************************/
10850
10851 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10852                                      struct spoolss_DeletePrintProcessor *r)
10853 {
10854         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10855         return WERR_NOT_SUPPORTED;
10856 }
10857
10858 /****************************************************************
10859  _spoolss_AddPrintProvidor
10860 ****************************************************************/
10861
10862 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10863                                  struct spoolss_AddPrintProvidor *r)
10864 {
10865         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10866         return WERR_NOT_SUPPORTED;
10867 }
10868
10869 /****************************************************************
10870  _spoolss_DeletePrintProvidor
10871 ****************************************************************/
10872
10873 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10874                                     struct spoolss_DeletePrintProvidor *r)
10875 {
10876         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10877         return WERR_NOT_SUPPORTED;
10878 }
10879
10880 /****************************************************************
10881  _spoolss_FindFirstPrinterChangeNotification
10882 ****************************************************************/
10883
10884 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10885                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10886 {
10887         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10888         return WERR_NOT_SUPPORTED;
10889 }
10890
10891 /****************************************************************
10892  _spoolss_FindNextPrinterChangeNotification
10893 ****************************************************************/
10894
10895 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10896                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10897 {
10898         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10899         return WERR_NOT_SUPPORTED;
10900 }
10901
10902 /****************************************************************
10903  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10904 ****************************************************************/
10905
10906 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10907                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10908 {
10909         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10910         return WERR_NOT_SUPPORTED;
10911 }
10912
10913 /****************************************************************
10914  _spoolss_ReplyOpenPrinter
10915 ****************************************************************/
10916
10917 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10918                                  struct spoolss_ReplyOpenPrinter *r)
10919 {
10920         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10921         return WERR_NOT_SUPPORTED;
10922 }
10923
10924 /****************************************************************
10925  _spoolss_RouterReplyPrinter
10926 ****************************************************************/
10927
10928 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10929                                    struct spoolss_RouterReplyPrinter *r)
10930 {
10931         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10932         return WERR_NOT_SUPPORTED;
10933 }
10934
10935 /****************************************************************
10936  _spoolss_ReplyClosePrinter
10937 ****************************************************************/
10938
10939 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10940                                   struct spoolss_ReplyClosePrinter *r)
10941 {
10942         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10943         return WERR_NOT_SUPPORTED;
10944 }
10945
10946 /****************************************************************
10947  _spoolss_AddPortEx
10948 ****************************************************************/
10949
10950 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10951                           struct spoolss_AddPortEx *r)
10952 {
10953         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10954         return WERR_NOT_SUPPORTED;
10955 }
10956
10957 /****************************************************************
10958  _spoolss_RouterFindFirstPrinterChangeNotification
10959 ****************************************************************/
10960
10961 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10962                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10963 {
10964         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10965         return WERR_NOT_SUPPORTED;
10966 }
10967
10968 /****************************************************************
10969  _spoolss_SpoolerInit
10970 ****************************************************************/
10971
10972 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10973                             struct spoolss_SpoolerInit *r)
10974 {
10975         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10976         return WERR_NOT_SUPPORTED;
10977 }
10978
10979 /****************************************************************
10980  _spoolss_ResetPrinterEx
10981 ****************************************************************/
10982
10983 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10984                                struct spoolss_ResetPrinterEx *r)
10985 {
10986         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10987         return WERR_NOT_SUPPORTED;
10988 }
10989
10990 /****************************************************************
10991  _spoolss_RouterReplyPrinterEx
10992 ****************************************************************/
10993
10994 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10995                                      struct spoolss_RouterReplyPrinterEx *r)
10996 {
10997         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10998         return WERR_NOT_SUPPORTED;
10999 }
11000
11001 /****************************************************************
11002  _spoolss_44
11003 ****************************************************************/
11004
11005 WERROR _spoolss_44(struct pipes_struct *p,
11006                    struct spoolss_44 *r)
11007 {
11008         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11009         return WERR_NOT_SUPPORTED;
11010 }
11011
11012 /****************************************************************
11013  _spoolss_SetPort
11014 ****************************************************************/
11015
11016 WERROR _spoolss_SetPort(struct pipes_struct *p,
11017                         struct spoolss_SetPort *r)
11018 {
11019         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11020         return WERR_NOT_SUPPORTED;
11021 }
11022
11023 /****************************************************************
11024  _spoolss_4a
11025 ****************************************************************/
11026
11027 WERROR _spoolss_4a(struct pipes_struct *p,
11028                    struct spoolss_4a *r)
11029 {
11030         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11031         return WERR_NOT_SUPPORTED;
11032 }
11033
11034 /****************************************************************
11035  _spoolss_4b
11036 ****************************************************************/
11037
11038 WERROR _spoolss_4b(struct pipes_struct *p,
11039                    struct spoolss_4b *r)
11040 {
11041         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11042         return WERR_NOT_SUPPORTED;
11043 }
11044
11045 /****************************************************************
11046  _spoolss_4c
11047 ****************************************************************/
11048
11049 WERROR _spoolss_4c(struct pipes_struct *p,
11050                    struct spoolss_4c *r)
11051 {
11052         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11053         return WERR_NOT_SUPPORTED;
11054 }
11055
11056 /****************************************************************
11057  _spoolss_53
11058 ****************************************************************/
11059
11060 WERROR _spoolss_53(struct pipes_struct *p,
11061                    struct spoolss_53 *r)
11062 {
11063         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11064         return WERR_NOT_SUPPORTED;
11065 }
11066
11067 /****************************************************************
11068  _spoolss_AddPerMachineConnection
11069 ****************************************************************/
11070
11071 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
11072                                         struct spoolss_AddPerMachineConnection *r)
11073 {
11074         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11075         return WERR_NOT_SUPPORTED;
11076 }
11077
11078 /****************************************************************
11079  _spoolss_DeletePerMachineConnection
11080 ****************************************************************/
11081
11082 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
11083                                            struct spoolss_DeletePerMachineConnection *r)
11084 {
11085         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11086         return WERR_NOT_SUPPORTED;
11087 }
11088
11089 /****************************************************************
11090  _spoolss_EnumPerMachineConnections
11091 ****************************************************************/
11092
11093 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
11094                                           struct spoolss_EnumPerMachineConnections *r)
11095 {
11096         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11097         return WERR_NOT_SUPPORTED;
11098 }
11099
11100 /****************************************************************
11101  _spoolss_5a
11102 ****************************************************************/
11103
11104 WERROR _spoolss_5a(struct pipes_struct *p,
11105                    struct spoolss_5a *r)
11106 {
11107         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11108         return WERR_NOT_SUPPORTED;
11109 }
11110
11111 /****************************************************************
11112  _spoolss_5b
11113 ****************************************************************/
11114
11115 WERROR _spoolss_5b(struct pipes_struct *p,
11116                    struct spoolss_5b *r)
11117 {
11118         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11119         return WERR_NOT_SUPPORTED;
11120 }
11121
11122 /****************************************************************
11123  _spoolss_5c
11124 ****************************************************************/
11125
11126 WERROR _spoolss_5c(struct pipes_struct *p,
11127                    struct spoolss_5c *r)
11128 {
11129         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11130         return WERR_NOT_SUPPORTED;
11131 }
11132
11133 /****************************************************************
11134  _spoolss_5d
11135 ****************************************************************/
11136
11137 WERROR _spoolss_5d(struct pipes_struct *p,
11138                    struct spoolss_5d *r)
11139 {
11140         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11141         return WERR_NOT_SUPPORTED;
11142 }
11143
11144 /****************************************************************
11145  _spoolss_5e
11146 ****************************************************************/
11147
11148 WERROR _spoolss_5e(struct pipes_struct *p,
11149                    struct spoolss_5e *r)
11150 {
11151         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11152         return WERR_NOT_SUPPORTED;
11153 }
11154
11155 /****************************************************************
11156  _spoolss_5f
11157 ****************************************************************/
11158
11159 WERROR _spoolss_5f(struct pipes_struct *p,
11160                    struct spoolss_5f *r)
11161 {
11162         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11163         return WERR_NOT_SUPPORTED;
11164 }
11165
11166 /****************************************************************
11167  _spoolss_60
11168 ****************************************************************/
11169
11170 WERROR _spoolss_60(struct pipes_struct *p,
11171                    struct spoolss_60 *r)
11172 {
11173         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11174         return WERR_NOT_SUPPORTED;
11175 }
11176
11177 /****************************************************************
11178  _spoolss_SendRecvBidiData
11179 ****************************************************************/
11180
11181 WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
11182                                  struct spoolss_SendRecvBidiData *r)
11183 {
11184         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11185         return WERR_NOT_SUPPORTED;
11186 }
11187
11188 /****************************************************************
11189  _spoolss_62
11190 ****************************************************************/
11191
11192 WERROR _spoolss_62(struct pipes_struct *p,
11193                    struct spoolss_62 *r)
11194 {
11195         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11196         return WERR_NOT_SUPPORTED;
11197 }
11198
11199 /****************************************************************
11200  _spoolss_63
11201 ****************************************************************/
11202
11203 WERROR _spoolss_63(struct pipes_struct *p,
11204                    struct spoolss_63 *r)
11205 {
11206         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11207         return WERR_NOT_SUPPORTED;
11208 }
11209
11210 /****************************************************************
11211  _spoolss_64
11212 ****************************************************************/
11213
11214 WERROR _spoolss_64(struct pipes_struct *p,
11215                    struct spoolss_64 *r)
11216 {
11217         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11218         return WERR_NOT_SUPPORTED;
11219 }
11220
11221 /****************************************************************
11222  _spoolss_65
11223 ****************************************************************/
11224
11225 WERROR _spoolss_65(struct pipes_struct *p,
11226                    struct spoolss_65 *r)
11227 {
11228         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11229         return WERR_NOT_SUPPORTED;
11230 }
11231
11232 /****************************************************************
11233  _spoolss_GetCorePrinterDrivers
11234 ****************************************************************/
11235
11236 HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11237                                        struct spoolss_GetCorePrinterDrivers *r)
11238 {
11239         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11240         return HRES_ERROR_NOT_SUPPORTED;
11241 }
11242
11243 /****************************************************************
11244  _spoolss_67
11245 ****************************************************************/
11246
11247 WERROR _spoolss_67(struct pipes_struct *p,
11248                    struct spoolss_67 *r)
11249 {
11250         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11251         return WERR_NOT_SUPPORTED;
11252 }
11253
11254 /****************************************************************
11255  _spoolss_GetPrinterDriverPackagePath
11256 ****************************************************************/
11257
11258 HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11259                                              struct spoolss_GetPrinterDriverPackagePath *r)
11260 {
11261         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11262         return HRES_ERROR_NOT_SUPPORTED;
11263 }
11264
11265 /****************************************************************
11266  _spoolss_69
11267 ****************************************************************/
11268
11269 WERROR _spoolss_69(struct pipes_struct *p,
11270                    struct spoolss_69 *r)
11271 {
11272         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11273         return WERR_NOT_SUPPORTED;
11274 }
11275
11276 /****************************************************************
11277  _spoolss_6a
11278 ****************************************************************/
11279
11280 WERROR _spoolss_6a(struct pipes_struct *p,
11281                    struct spoolss_6a *r)
11282 {
11283         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11284         return WERR_NOT_SUPPORTED;
11285 }
11286
11287 /****************************************************************
11288  _spoolss_6b
11289 ****************************************************************/
11290
11291 WERROR _spoolss_6b(struct pipes_struct *p,
11292                    struct spoolss_6b *r)
11293 {
11294         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11295         return WERR_NOT_SUPPORTED;
11296 }
11297
11298 /****************************************************************
11299  _spoolss_6c
11300 ****************************************************************/
11301
11302 WERROR _spoolss_6c(struct pipes_struct *p,
11303                    struct spoolss_6c *r)
11304 {
11305         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11306         return WERR_NOT_SUPPORTED;
11307 }
11308
11309 /****************************************************************
11310  _spoolss_6d
11311 ****************************************************************/
11312
11313 WERROR _spoolss_6d(struct pipes_struct *p,
11314                    struct spoolss_6d *r)
11315 {
11316         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11317         return WERR_NOT_SUPPORTED;
11318 }
11319
11320 /****************************************************************
11321  _spoolss_GetJobNamedPropertyValue
11322 ****************************************************************/
11323
11324 WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
11325                                          struct spoolss_GetJobNamedPropertyValue *r)
11326 {
11327         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11328         return WERR_NOT_SUPPORTED;
11329 }
11330
11331 /****************************************************************
11332  _spoolss_SetJobNamedProperty
11333 ****************************************************************/
11334
11335 WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
11336                                     struct spoolss_SetJobNamedProperty *r)
11337 {
11338         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11339         return WERR_NOT_SUPPORTED;
11340 }
11341
11342 /****************************************************************
11343  _spoolss_DeleteJobNamedProperty
11344 ****************************************************************/
11345
11346 WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
11347                                        struct spoolss_DeleteJobNamedProperty *r)
11348 {
11349         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11350         return WERR_NOT_SUPPORTED;
11351 }
11352
11353 /****************************************************************
11354  _spoolss_EnumJobNamedProperties
11355 ****************************************************************/
11356
11357 WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
11358                                        struct spoolss_EnumJobNamedProperties *r)
11359 {
11360         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11361         return WERR_NOT_SUPPORTED;
11362 }
11363
11364 /****************************************************************
11365  _spoolss_72
11366 ****************************************************************/
11367
11368 WERROR _spoolss_72(struct pipes_struct *p,
11369                    struct spoolss_72 *r)
11370 {
11371         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11372         return WERR_NOT_SUPPORTED;
11373 }
11374
11375 /****************************************************************
11376  _spoolss_73
11377 ****************************************************************/
11378
11379 WERROR _spoolss_73(struct pipes_struct *p,
11380                    struct spoolss_73 *r)
11381 {
11382         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11383         return WERR_NOT_SUPPORTED;
11384 }
11385
11386 /****************************************************************
11387  _spoolss_RpcLogJobInfoForBranchOffice
11388 ****************************************************************/
11389
11390 WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
11391                                           struct spoolss_LogJobInfoForBranchOffice *r)
11392 {
11393         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11394         return WERR_NOT_SUPPORTED;
11395 }