Update smbrun to allow for settings environment variables.
[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         ret = smbrun(command, NULL, NULL);
405         if (ret == 0) {
406                 /* Tell everyone we updated smb.conf. */
407                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
408         }
409
410         if ( is_print_op )
411                 unbecome_root();
412
413         /********** END SePrintOperatorPrivlege BLOCK **********/
414
415         DEBUGADD(10,("returned [%d]\n", ret));
416
417         TALLOC_FREE(command);
418
419         if (ret != 0)
420                 return WERR_INVALID_HANDLE; /* What to return here? */
421
422         return WERR_OK;
423 }
424
425 /****************************************************************************
426  Delete a printer given a handle.
427 ****************************************************************************/
428
429 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
430 {
431         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
432         WERROR result;
433
434         if (!Printer) {
435                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
436                         OUR_HANDLE(hnd)));
437                 return WERR_INVALID_HANDLE;
438         }
439
440         /*
441          * It turns out that Windows allows delete printer on a handle
442          * opened by an admin user, then used on a pipe handle created
443          * by an anonymous user..... but they're working on security.... riiight !
444          * JRA.
445          */
446
447         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
448                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
449                 return WERR_ACCESS_DENIED;
450         }
451
452         /* this does not need a become root since the access check has been
453            done on the handle already */
454
455         result = winreg_delete_printer_key_internal(p->mem_ctx,
456                                            get_session_info_system(),
457                                            p->msg_ctx,
458                                            Printer->sharename,
459                                            "");
460         if (!W_ERROR_IS_OK(result)) {
461                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
462                 return WERR_INVALID_HANDLE;
463         }
464
465         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
466                                      Printer->sharename, p->msg_ctx);
467         if (!W_ERROR_IS_OK(result)) {
468                 return result;
469         }
470         prune_printername_cache();
471         return WERR_OK;
472 }
473
474 /****************************************************************************
475  Return the snum of a printer corresponding to an handle.
476 ****************************************************************************/
477
478 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
479                              int *number, struct share_params **params)
480 {
481         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
482
483         if (!Printer) {
484                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
485                         OUR_HANDLE(hnd)));
486                 return false;
487         }
488
489         switch (Printer->printer_type) {
490                 case SPLHND_PRINTER:
491                         DEBUG(4,("short name:%s\n", Printer->sharename));
492                         *number = print_queue_snum(Printer->sharename);
493                         return (*number != -1);
494                 case SPLHND_SERVER:
495                         return false;
496                 default:
497                         return false;
498         }
499 }
500
501 /****************************************************************************
502  Set printer handle type.
503  Check if it's \\server or \\server\printer
504 ****************************************************************************/
505
506 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
507 {
508         DEBUG(3,("Setting printer type=%s\n", handlename));
509
510         /* it's a print server */
511         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
512                 DEBUGADD(4,("Printer is a print server\n"));
513                 Printer->printer_type = SPLHND_SERVER;
514         }
515         /* it's a printer (set_printer_hnd_name() will handle port monitors */
516         else {
517                 DEBUGADD(4,("Printer is a printer\n"));
518                 Printer->printer_type = SPLHND_PRINTER;
519         }
520
521         return true;
522 }
523
524 static void prune_printername_cache_fn(const char *key, const char *value,
525                                        time_t timeout, void *private_data)
526 {
527         gencache_del(key);
528 }
529
530 static void prune_printername_cache(void)
531 {
532         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
533 }
534
535 /****************************************************************************
536  Set printer handle name..  Accept names like \\server, \\server\printer,
537  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
538  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
539  XcvDataPort() interface.
540 ****************************************************************************/
541
542 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
543                                    const struct auth_session_info *session_info,
544                                    struct messaging_context *msg_ctx,
545                                    struct printer_handle *Printer,
546                                    const char *handlename)
547 {
548         int snum;
549         int n_services=lp_numservices();
550         char *aprinter;
551         const char *printername;
552         const char *servername = NULL;
553         fstring sname;
554         bool found = false;
555         struct spoolss_PrinterInfo2 *info2 = NULL;
556         WERROR result;
557         char *p;
558
559         /*
560          * Hopefully nobody names his printers like this. Maybe \ or ,
561          * are illegal in printer names even?
562          */
563         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
564         char *cache_key;
565         char *tmp;
566
567         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
568                 (unsigned long)strlen(handlename)));
569
570         aprinter = discard_const_p(char, handlename);
571         if ( *handlename == '\\' ) {
572                 servername = canon_servername(handlename);
573                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
574                         *aprinter = '\0';
575                         aprinter++;
576                 }
577                 if (!is_myname_or_ipaddr(servername)) {
578                         return WERR_INVALID_PRINTER_NAME;
579                 }
580                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
581                 if (Printer->servername == NULL) {
582                         return WERR_NOT_ENOUGH_MEMORY;
583                 }
584         }
585
586         if (Printer->printer_type == SPLHND_SERVER) {
587                 return WERR_OK;
588         }
589
590         if (Printer->printer_type != SPLHND_PRINTER) {
591                 return WERR_INVALID_HANDLE;
592         }
593
594         DEBUGADD(5, ("searching for [%s]\n", aprinter));
595
596         p = strchr(aprinter, ',');
597         if (p != NULL) {
598                 char *p2 = p;
599                 p++;
600                 if (*p == ' ') {
601                         p++;
602                 }
603                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
604                         *p2 = '\0';
605                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
606                         *p2 = '\0';
607                 }
608         }
609
610         if (p) {
611                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
612         }
613
614         /* check for the Port Monitor Interface */
615         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
616                 Printer->printer_type = SPLHND_PORTMON_TCP;
617                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
618                 found = true;
619         }
620         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
621                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
622                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
623                 found = true;
624         }
625
626         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
627         if (cache_key == NULL) {
628                 return WERR_NOT_ENOUGH_MEMORY;
629         }
630
631         /*
632          * With hundreds of printers, the "for" loop iterating all
633          * shares can be quite expensive, as it is done on every
634          * OpenPrinter. The loop maps "aprinter" to "sname", the
635          * result of which we cache in gencache.
636          */
637         if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
638                 found = (strcmp(tmp, printer_not_found) != 0);
639                 if (!found) {
640                         DEBUG(4, ("Printer %s not found\n", aprinter));
641                         TALLOC_FREE(tmp);
642                         return WERR_INVALID_PRINTER_NAME;
643                 }
644                 fstrcpy(sname, tmp);
645                 TALLOC_FREE(tmp);
646         }
647
648         /* Search all sharenames first as this is easier than pulling
649            the printer_info_2 off of disk. Don't use find_service() since
650            that calls out to map_username() */
651
652         /* do another loop to look for printernames */
653         for (snum = 0; !found && snum < n_services; snum++) {
654                 const char *printer = lp_const_servicename(snum);
655
656                 /* no point going on if this is not a printer */
657                 if (!(lp_snum_ok(snum) && lp_printable(snum))) {
658                         continue;
659                 }
660
661                 /* ignore [printers] share */
662                 if (strequal(printer, "printers")) {
663                         continue;
664                 }
665
666                 fstrcpy(sname, printer);
667                 if (strequal(aprinter, printer)) {
668                         found = true;
669                         break;
670                 }
671
672                 /* no point looking up the printer object if
673                    we aren't allowing printername != sharename */
674                 if (lp_force_printername(snum)) {
675                         continue;
676                 }
677
678                 result = winreg_get_printer_internal(mem_ctx,
679                                             session_info,
680                                             msg_ctx,
681                                             sname,
682                                             &info2);
683                 if ( !W_ERROR_IS_OK(result) ) {
684                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
685                                  sname, win_errstr(result)));
686                         continue;
687                 }
688
689                 printername = strrchr(info2->printername, '\\');
690                 if (printername == NULL) {
691                         printername = info2->printername;
692                 } else {
693                         printername++;
694                 }
695
696                 if (strequal(printername, aprinter)) {
697                         found = true;
698                         break;
699                 }
700
701                 DEBUGADD(10, ("printername: %s\n", printername));
702
703                 TALLOC_FREE(info2);
704         }
705
706         if (!found) {
707                 gencache_set(cache_key, printer_not_found,
708                              time_mono(NULL) + 300);
709                 TALLOC_FREE(cache_key);
710                 DEBUGADD(4,("Printer not found\n"));
711                 return WERR_INVALID_PRINTER_NAME;
712         }
713
714         gencache_set(cache_key, sname, time_mono(NULL) + 300);
715         TALLOC_FREE(cache_key);
716
717         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
718
719         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
720
721         return WERR_OK;
722 }
723
724 /****************************************************************************
725  Find first available printer slot. creates a printer handle for you.
726  ****************************************************************************/
727
728 static WERROR open_printer_hnd(struct pipes_struct *p,
729                                struct policy_handle *hnd,
730                                const char *name,
731                                uint32_t access_granted)
732 {
733         struct printer_handle *new_printer;
734         WERROR result;
735
736         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
737
738         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
739         if (new_printer == NULL) {
740                 return WERR_NOT_ENOUGH_MEMORY;
741         }
742         talloc_set_destructor(new_printer, printer_entry_destructor);
743
744         /* This also steals the printer_handle on the policy_handle */
745         if (!create_policy_hnd(p, hnd, new_printer)) {
746                 TALLOC_FREE(new_printer);
747                 return WERR_INVALID_HANDLE;
748         }
749
750         /* Add to the internal list. */
751         DLIST_ADD(printers_list, new_printer);
752
753         new_printer->notify.option=NULL;
754
755         if (!set_printer_hnd_printertype(new_printer, name)) {
756                 close_printer_handle(p, hnd);
757                 return WERR_INVALID_HANDLE;
758         }
759
760         result = set_printer_hnd_name(p->mem_ctx,
761                                       get_session_info_system(),
762                                       p->msg_ctx,
763                                       new_printer, name);
764         if (!W_ERROR_IS_OK(result)) {
765                 close_printer_handle(p, hnd);
766                 return result;
767         }
768
769         new_printer->access_granted = access_granted;
770
771         DEBUG(5, ("%d printer handles active\n",
772                   (int)num_pipe_handles(p)));
773
774         return WERR_OK;
775 }
776
777 /***************************************************************************
778  check to see if the client motify handle is monitoring the notification
779  given by (notify_type, notify_field).
780  **************************************************************************/
781
782 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
783                                       uint16_t notify_field)
784 {
785         return true;
786 }
787
788 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
789                                 uint16_t notify_field)
790 {
791         struct spoolss_NotifyOption *option = p->notify.option;
792         uint32_t i, j;
793
794         /*
795          * Flags should always be zero when the change notify
796          * is registered by the client's spooler.  A user Win32 app
797          * might use the flags though instead of the NOTIFY_OPTION_INFO
798          * --jerry
799          */
800
801         if (!option) {
802                 return false;
803         }
804
805         if (p->notify.flags)
806                 return is_monitoring_event_flags(
807                         p->notify.flags, notify_type, notify_field);
808
809         for (i = 0; i < option->count; i++) {
810
811                 /* Check match for notify_type */
812
813                 if (option->types[i].type != notify_type)
814                         continue;
815
816                 /* Check match for field */
817
818                 for (j = 0; j < option->types[i].count; j++) {
819                         if (option->types[i].fields[j].field == notify_field) {
820                                 return true;
821                         }
822                 }
823         }
824
825         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
826                    p->servername, p->sharename, notify_type, notify_field));
827
828         return false;
829 }
830
831 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
832         _data->data.integer[0] = _integer; \
833         _data->data.integer[1] = 0;
834
835
836 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
837         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
838         if (!_data->data.string.string) {\
839                 _data->data.string.size = 0; \
840         } \
841         _data->data.string.size = strlen_m_term(_p) * 2;
842
843 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
844         _data->data.devmode.devmode = _devmode;
845
846 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
847                                    struct tm *t,
848                                    const char **pp,
849                                    uint32_t *plen)
850 {
851         struct spoolss_Time st;
852         uint32_t len = 16;
853         char *p;
854
855         if (!init_systemtime(&st, t)) {
856                 return;
857         }
858
859         p = talloc_array(mem_ctx, char, len);
860         if (!p) {
861                 return;
862         }
863
864         /*
865          * Systemtime must be linearized as a set of UINT16's.
866          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
867          */
868
869         SSVAL(p, 0, st.year);
870         SSVAL(p, 2, st.month);
871         SSVAL(p, 4, st.day_of_week);
872         SSVAL(p, 6, st.day);
873         SSVAL(p, 8, st.hour);
874         SSVAL(p, 10, st.minute);
875         SSVAL(p, 12, st.second);
876         SSVAL(p, 14, st.millisecond);
877
878         *pp = p;
879         *plen = len;
880 }
881
882 /* Convert a notification message to a struct spoolss_Notify */
883
884 static void notify_one_value(struct spoolss_notify_msg *msg,
885                              struct spoolss_Notify *data,
886                              TALLOC_CTX *mem_ctx)
887 {
888         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
889 }
890
891 static void notify_string(struct spoolss_notify_msg *msg,
892                           struct spoolss_Notify *data,
893                           TALLOC_CTX *mem_ctx)
894 {
895         /* The length of the message includes the trailing \0 */
896
897         data->data.string.size = msg->len * 2;
898         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
899         if (!data->data.string.string) {
900                 data->data.string.size = 0;
901                 return;
902         }
903 }
904
905 static void notify_system_time(struct spoolss_notify_msg *msg,
906                                struct spoolss_Notify *data,
907                                TALLOC_CTX *mem_ctx)
908 {
909         data->data.string.string = NULL;
910         data->data.string.size = 0;
911
912         if (msg->len != sizeof(time_t)) {
913                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
914                           msg->len));
915                 return;
916         }
917
918         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
919                                &data->data.string.string,
920                                &data->data.string.size);
921 }
922
923 struct notify2_message_table {
924         const char *name;
925         void (*fn)(struct spoolss_notify_msg *msg,
926                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
927 };
928
929 static struct notify2_message_table printer_notify_table[] = {
930         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
931         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
932         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
933         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
934         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
935         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
936         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
937         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
938         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
939         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
940         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
941         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
942         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
943         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
944         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
945         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
946         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
947         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
948         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
949 };
950
951 static struct notify2_message_table job_notify_table[] = {
952         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
953         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
954         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
955         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
956         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
957         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
958         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
959         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
960         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
961         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
962         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
963         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
964         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
965         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
966         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
967         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
968         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
969         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
970         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
971         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
972         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
973         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
974         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
975         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
976 };
977
978
979 /***********************************************************************
980  Allocate talloc context for container object
981  **********************************************************************/
982
983 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
984 {
985         if ( !ctr )
986                 return;
987
988         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
989
990         return;
991 }
992
993 /***********************************************************************
994  release all allocated memory and zero out structure
995  **********************************************************************/
996
997 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
998 {
999         if ( !ctr )
1000                 return;
1001
1002         if ( ctr->ctx )
1003                 talloc_destroy(ctr->ctx);
1004
1005         ZERO_STRUCTP(ctr);
1006
1007         return;
1008 }
1009
1010 /***********************************************************************
1011  **********************************************************************/
1012
1013 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1014 {
1015         if ( !ctr )
1016                 return NULL;
1017
1018         return ctr->ctx;
1019 }
1020
1021 /***********************************************************************
1022  **********************************************************************/
1023
1024 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1025 {
1026         if ( !ctr || !ctr->msg_groups )
1027                 return NULL;
1028
1029         if ( idx >= ctr->num_groups )
1030                 return NULL;
1031
1032         return &ctr->msg_groups[idx];
1033
1034 }
1035
1036 /***********************************************************************
1037  How many groups of change messages do we have ?
1038  **********************************************************************/
1039
1040 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1041 {
1042         if ( !ctr )
1043                 return 0;
1044
1045         return ctr->num_groups;
1046 }
1047
1048 /***********************************************************************
1049  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1050  **********************************************************************/
1051
1052 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1053 {
1054         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1055         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1056         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1057         int                             i, new_slot;
1058
1059         if ( !ctr || !msg )
1060                 return 0;
1061
1062         /* loop over all groups looking for a matching printer name */
1063
1064         for ( i=0; i<ctr->num_groups; i++ ) {
1065                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1066                         break;
1067         }
1068
1069         /* add a new group? */
1070
1071         if ( i == ctr->num_groups ) {
1072                 ctr->num_groups++;
1073
1074                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1075                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1076                         return 0;
1077                 }
1078                 ctr->msg_groups = groups;
1079
1080                 /* clear the new entry and set the printer name */
1081
1082                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1083                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1084         }
1085
1086         /* add the change messages; 'i' is the correct index now regardless */
1087
1088         msg_grp = &ctr->msg_groups[i];
1089
1090         msg_grp->num_msgs++;
1091
1092         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1093                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1094                 return 0;
1095         }
1096         msg_grp->msgs = msg_list;
1097
1098         new_slot = msg_grp->num_msgs-1;
1099         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1100
1101         /* need to allocate own copy of data */
1102
1103         if ( msg->len != 0 )
1104                 msg_grp->msgs[new_slot].notify.data = (char *)
1105                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1106
1107         return ctr->num_groups;
1108 }
1109
1110 static void construct_info_data(struct spoolss_Notify *info_data,
1111                                 enum spoolss_NotifyType type,
1112                                 uint16_t field, int id);
1113
1114 /***********************************************************************
1115  Send a change notication message on all handles which have a call
1116  back registered
1117  **********************************************************************/
1118
1119 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1120                                   struct printer_handle *prn_hnd,
1121                                   SPOOLSS_NOTIFY_MSG *messages,
1122                                   uint32_t num_msgs,
1123                                   struct spoolss_Notify **_notifies,
1124                                   int *_count)
1125 {
1126         struct spoolss_Notify *notifies;
1127         SPOOLSS_NOTIFY_MSG *msg;
1128         int count = 0;
1129         uint32_t id;
1130         int i;
1131
1132         notifies = talloc_zero_array(mem_ctx,
1133                                      struct spoolss_Notify, num_msgs);
1134         if (!notifies) {
1135                 return ENOMEM;
1136         }
1137
1138         for (i = 0; i < num_msgs; i++) {
1139
1140                 msg = &messages[i];
1141
1142                 /* Are we monitoring this event? */
1143
1144                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1145                         continue;
1146                 }
1147
1148                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1149                            "for printer [%s]\n",
1150                            msg->type, msg->field, prn_hnd->sharename));
1151
1152                 /*
1153                  * if the is a printer notification handle and not a job
1154                  * notification type, then set the id to 0.
1155                  * Otherwise just use what was specified in the message.
1156                  *
1157                  * When registering change notification on a print server
1158                  * handle we always need to send back the id (snum) matching
1159                  * the printer for which the change took place.
1160                  * For change notify registered on a printer handle,
1161                  * this does not matter and the id should be 0.
1162                  *
1163                  * --jerry
1164                  */
1165
1166                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1167                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1168                         id = 0;
1169                 } else {
1170                         id = msg->id;
1171                 }
1172
1173                 /* Convert unix jobid to smb jobid */
1174
1175                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1176                         id = sysjob_to_jobid(msg->id);
1177
1178                         if (id == -1) {
1179                                 DEBUG(3, ("no such unix jobid %d\n",
1180                                           msg->id));
1181                                 continue;
1182                         }
1183                 }
1184
1185                 construct_info_data(&notifies[count],
1186                                     msg->type, msg->field, id);
1187
1188                 switch(msg->type) {
1189                 case PRINTER_NOTIFY_TYPE:
1190                         if (printer_notify_table[msg->field].fn) {
1191                                 printer_notify_table[msg->field].fn(msg,
1192                                                 &notifies[count], mem_ctx);
1193                         }
1194                         break;
1195
1196                 case JOB_NOTIFY_TYPE:
1197                         if (job_notify_table[msg->field].fn) {
1198                                 job_notify_table[msg->field].fn(msg,
1199                                                 &notifies[count], mem_ctx);
1200                         }
1201                         break;
1202
1203                 default:
1204                         DEBUG(5, ("Unknown notification type %d\n",
1205                                   msg->type));
1206                         continue;
1207                 }
1208
1209                 count++;
1210         }
1211
1212         *_notifies = notifies;
1213         *_count = count;
1214
1215         return 0;
1216 }
1217
1218 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1219                                 struct printer_handle *prn_hnd,
1220                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1221 {
1222         struct spoolss_Notify *notifies;
1223         int count = 0;
1224         union spoolss_ReplyPrinterInfo info;
1225         struct spoolss_NotifyInfo info0;
1226         uint32_t reply_result;
1227         NTSTATUS status;
1228         WERROR werr;
1229         int ret;
1230
1231         /* Is there notification on this handle? */
1232         if (prn_hnd->notify.cli_chan == NULL ||
1233             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1234             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1235             prn_hnd->notify.cli_chan->active_connections == 0) {
1236                 return 0;
1237         }
1238
1239         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1240                    prn_hnd->servername, prn_hnd->sharename));
1241
1242         /* For this printer? Print servers always receive notifications. */
1243         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1244             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1245                 return 0;
1246         }
1247
1248         DEBUG(10,("Our printer\n"));
1249
1250         /* build the array of change notifications */
1251         ret = build_notify2_messages(mem_ctx, prn_hnd,
1252                                      msg_group->msgs,
1253                                      msg_group->num_msgs,
1254                                      &notifies, &count);
1255         if (ret) {
1256                 return ret;
1257         }
1258
1259         info0.version   = 0x2;
1260         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1261         info0.count     = count;
1262         info0.notifies  = notifies;
1263
1264         info.info0 = &info0;
1265
1266         status = dcerpc_spoolss_RouterReplyPrinterEx(
1267                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1268                                 mem_ctx,
1269                                 &prn_hnd->notify.cli_hnd,
1270                                 prn_hnd->notify.change, /* color */
1271                                 prn_hnd->notify.flags,
1272                                 &reply_result,
1273                                 0, /* reply_type, must be 0 */
1274                                 info, &werr);
1275         if (!NT_STATUS_IS_OK(status)) {
1276                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1277                           "failed: %s\n",
1278                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1279                           nt_errstr(status)));
1280                 werr = ntstatus_to_werror(status);
1281         } else if (!W_ERROR_IS_OK(werr)) {
1282                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1283                           "failed: %s\n",
1284                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1285                           win_errstr(werr)));
1286         }
1287         switch (reply_result) {
1288         case 0:
1289                 break;
1290         case PRINTER_NOTIFY_INFO_DISCARDED:
1291         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1292         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1293                 break;
1294         default:
1295                 break;
1296         }
1297
1298         return 0;
1299 }
1300
1301 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1302 {
1303         struct printer_handle    *p;
1304         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1305         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1306         int ret;
1307
1308         if ( !msg_group ) {
1309                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1310                 return;
1311         }
1312
1313         if (!msg_group->msgs) {
1314                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1315                 return;
1316         }
1317
1318         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1319
1320         /* loop over all printers */
1321
1322         for (p = printers_list; p; p = p->next) {
1323                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1324                 if (ret) {
1325                         goto done;
1326                 }
1327         }
1328
1329 done:
1330         DEBUG(8,("send_notify2_changes: Exit...\n"));
1331         return;
1332 }
1333
1334 /***********************************************************************
1335  **********************************************************************/
1336
1337 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1338 {
1339
1340         uint32_t tv_sec, tv_usec;
1341         size_t offset = 0;
1342
1343         /* Unpack message */
1344
1345         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1346                              msg->printer);
1347
1348         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1349                                 &tv_sec, &tv_usec,
1350                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1351
1352         if (msg->len == 0)
1353                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1354                            &msg->notify.value[0], &msg->notify.value[1]);
1355         else
1356                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1357                            &msg->len, &msg->notify.data);
1358
1359         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1360                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1361
1362         tv->tv_sec = tv_sec;
1363         tv->tv_usec = tv_usec;
1364
1365         if (msg->len == 0)
1366                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1367                           msg->notify.value[1]));
1368         else
1369                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1370
1371         return true;
1372 }
1373
1374 /********************************************************************
1375  Receive a notify2 message list
1376  ********************************************************************/
1377
1378 static void receive_notify2_message_list(struct messaging_context *msg,
1379                                          void *private_data,
1380                                          uint32_t msg_type,
1381                                          struct server_id server_id,
1382                                          DATA_BLOB *data)
1383 {
1384         size_t                  msg_count, i;
1385         char                    *buf = (char *)data->data;
1386         char                    *msg_ptr;
1387         size_t                  msg_len;
1388         SPOOLSS_NOTIFY_MSG      notify;
1389         SPOOLSS_NOTIFY_MSG_CTR  messages;
1390         int                     num_groups;
1391
1392         if (data->length < 4) {
1393                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1394                 return;
1395         }
1396
1397         msg_count = IVAL(buf, 0);
1398         msg_ptr = buf + 4;
1399
1400         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1401
1402         if (msg_count == 0) {
1403                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1404                 return;
1405         }
1406
1407         /* initialize the container */
1408
1409         ZERO_STRUCT( messages );
1410         notify_msg_ctr_init( &messages );
1411
1412         /*
1413          * build message groups for each printer identified
1414          * in a change_notify msg.  Remember that a PCN message
1415          * includes the handle returned for the srv_spoolss_replyopenprinter()
1416          * call.  Therefore messages are grouped according to printer handle.
1417          */
1418
1419         for ( i=0; i<msg_count; i++ ) {
1420                 struct timeval msg_tv;
1421
1422                 if (msg_ptr + 4 - buf > data->length) {
1423                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1424                         return;
1425                 }
1426
1427                 msg_len = IVAL(msg_ptr,0);
1428                 msg_ptr += 4;
1429
1430                 if (msg_ptr + msg_len - buf > data->length) {
1431                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1432                         return;
1433                 }
1434
1435                 /* unpack messages */
1436
1437                 ZERO_STRUCT( notify );
1438                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1439                 msg_ptr += msg_len;
1440
1441                 /* add to correct list in container */
1442
1443                 notify_msg_ctr_addmsg( &messages, &notify );
1444
1445                 /* free memory that might have been allocated by notify2_unpack_msg() */
1446
1447                 if ( notify.len != 0 )
1448                         SAFE_FREE( notify.notify.data );
1449         }
1450
1451         /* process each group of messages */
1452
1453         num_groups = notify_msg_ctr_numgroups( &messages );
1454         for ( i=0; i<num_groups; i++ )
1455                 send_notify2_changes( &messages, i );
1456
1457
1458         /* cleanup */
1459
1460         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1461                 (uint32_t)msg_count ));
1462
1463         notify_msg_ctr_destroy( &messages );
1464
1465         return;
1466 }
1467
1468 /********************************************************************
1469  Send a message to ourself about new driver being installed
1470  so we can upgrade the information for each printer bound to this
1471  driver
1472  ********************************************************************/
1473
1474 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1475                                             struct messaging_context *msg_ctx)
1476 {
1477         int len = strlen(drivername);
1478
1479         if (!len)
1480                 return false;
1481
1482         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1483                 drivername));
1484
1485         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1486                            MSG_PRINTER_DRVUPGRADE,
1487                            (const uint8_t *)drivername, len+1);
1488
1489         return true;
1490 }
1491
1492 void srv_spoolss_cleanup(void)
1493 {
1494         struct printer_session_counter *session_counter;
1495
1496         for (session_counter = counter_list;
1497              session_counter != NULL;
1498              session_counter = counter_list) {
1499                 DLIST_REMOVE(counter_list, session_counter);
1500                 TALLOC_FREE(session_counter);
1501         }
1502 }
1503
1504 /**********************************************************************
1505  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1506  over all printers, upgrading ones as necessary
1507  This is now *ONLY* called inside the background lpq updater. JRA.
1508  **********************************************************************/
1509
1510 void do_drv_upgrade_printer(struct messaging_context *msg,
1511                             void *private_data,
1512                             uint32_t msg_type,
1513                             struct server_id server_id,
1514                             DATA_BLOB *data)
1515 {
1516         TALLOC_CTX *tmp_ctx;
1517         const struct auth_session_info *session_info = get_session_info_system();
1518         struct spoolss_PrinterInfo2 *pinfo2;
1519         WERROR result;
1520         const char *drivername;
1521         int snum;
1522         int n_services = lp_numservices();
1523         struct dcerpc_binding_handle *b = NULL;
1524
1525         tmp_ctx = talloc_new(NULL);
1526         if (!tmp_ctx) return;
1527
1528         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1529         if (!drivername) {
1530                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1531                 goto done;
1532         }
1533
1534         DEBUG(10, ("do_drv_upgrade_printer: "
1535                    "Got message for new driver [%s]\n", drivername));
1536
1537         /* Iterate the printer list */
1538
1539         for (snum = 0; snum < n_services; snum++) {
1540                 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1541                         continue;
1542                 }
1543
1544                 /* ignore [printers] share */
1545                 if (strequal(lp_const_servicename(snum), "printers")) {
1546                         continue;
1547                 }
1548
1549                 if (b == NULL) {
1550                         result = winreg_printer_binding_handle(tmp_ctx,
1551                                                                session_info,
1552                                                                msg,
1553                                                                &b);
1554                         if (!W_ERROR_IS_OK(result)) {
1555                                 break;
1556                         }
1557                 }
1558
1559                 result = winreg_get_printer(tmp_ctx, b,
1560                                             lp_const_servicename(snum),
1561                                             &pinfo2);
1562
1563                 if (!W_ERROR_IS_OK(result)) {
1564                         continue;
1565                 }
1566
1567                 if (!pinfo2->drivername) {
1568                         continue;
1569                 }
1570
1571                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1572                         continue;
1573                 }
1574
1575                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1576
1577                 /* all we care about currently is the change_id */
1578                 result = winreg_printer_update_changeid(tmp_ctx, b,
1579                                                         pinfo2->printername);
1580
1581                 if (!W_ERROR_IS_OK(result)) {
1582                         DEBUG(3, ("do_drv_upgrade_printer: "
1583                                   "Failed to update changeid [%s]\n",
1584                                   win_errstr(result)));
1585                 }
1586         }
1587
1588         /* all done */
1589 done:
1590         talloc_free(tmp_ctx);
1591 }
1592
1593 /********************************************************************
1594  Update the cache for all printq's with a registered client
1595  connection
1596  ********************************************************************/
1597
1598 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1599 {
1600         struct printer_handle *printer = printers_list;
1601         int snum;
1602
1603         /* loop through all printers and update the cache where
1604            a client is connected */
1605         while (printer) {
1606                 if ((printer->printer_type == SPLHND_PRINTER) &&
1607                     ((printer->notify.cli_chan != NULL) &&
1608                      (printer->notify.cli_chan->active_connections > 0))) {
1609                         snum = print_queue_snum(printer->sharename);
1610                         print_queue_status(msg_ctx, snum, NULL, NULL);
1611                 }
1612
1613                 printer = printer->next;
1614         }
1615
1616         return;
1617 }
1618
1619 /****************************************************************
1620  _spoolss_OpenPrinter
1621 ****************************************************************/
1622
1623 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1624                             struct spoolss_OpenPrinter *r)
1625 {
1626         struct spoolss_OpenPrinterEx e;
1627         struct spoolss_UserLevel1 level1;
1628         WERROR werr;
1629
1630         ZERO_STRUCT(level1);
1631
1632         e.in.printername        = r->in.printername;
1633         e.in.datatype           = r->in.datatype;
1634         e.in.devmode_ctr        = r->in.devmode_ctr;
1635         e.in.access_mask        = r->in.access_mask;
1636         e.in.userlevel_ctr.level                = 1;
1637         e.in.userlevel_ctr.user_info.level1     = &level1;
1638
1639         e.out.handle            = r->out.handle;
1640
1641         werr = _spoolss_OpenPrinterEx(p, &e);
1642
1643         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
1644                 /* OpenPrinterEx returns this for a bad
1645                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1646                  * instead.
1647                  */
1648                 werr = WERR_INVALID_PRINTER_NAME;
1649         }
1650
1651         return werr;
1652 }
1653
1654 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1655                               struct spoolss_DeviceMode *orig,
1656                               struct spoolss_DeviceMode **dest)
1657 {
1658         struct spoolss_DeviceMode *dm;
1659
1660         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1661         if (!dm) {
1662                 return WERR_NOT_ENOUGH_MEMORY;
1663         }
1664
1665         /* copy all values, then duplicate strings and structs */
1666         *dm = *orig;
1667
1668         dm->devicename = talloc_strdup(dm, orig->devicename);
1669         if (!dm->devicename) {
1670                 return WERR_NOT_ENOUGH_MEMORY;
1671         }
1672         dm->formname = talloc_strdup(dm, orig->formname);
1673         if (!dm->formname) {
1674                 return WERR_NOT_ENOUGH_MEMORY;
1675         }
1676         if (orig->driverextra_data.data) {
1677                 dm->driverextra_data.data =
1678                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1679                                         orig->driverextra_data.length);
1680                 if (!dm->driverextra_data.data) {
1681                         return WERR_NOT_ENOUGH_MEMORY;
1682                 }
1683         }
1684
1685         *dest = dm;
1686         return WERR_OK;
1687 }
1688
1689 /****************************************************************
1690  _spoolss_OpenPrinterEx
1691 ****************************************************************/
1692
1693 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1694                               struct spoolss_OpenPrinterEx *r)
1695 {
1696         int snum;
1697         char *raddr;
1698         char *rhost;
1699         struct printer_handle *Printer=NULL;
1700         WERROR result;
1701         int rc;
1702
1703         if (!r->in.printername) {
1704                 return WERR_INVALID_PARAMETER;
1705         }
1706
1707         if (!*r->in.printername) {
1708                 return WERR_INVALID_PARAMETER;
1709         }
1710
1711         if (r->in.userlevel_ctr.level > 3) {
1712                 return WERR_INVALID_PARAMETER;
1713         }
1714         if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1715             (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1716             (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1717                 return WERR_INVALID_PARAMETER;
1718         }
1719
1720         /*
1721          * The printcap printer share inventory is updated on client
1722          * enumeration. For clients that do not perform enumeration prior to
1723          * access, such as cupssmbadd, we reinitialise the printer share
1724          * inventory on open as well.
1725          */
1726         become_root();
1727         delete_and_reload_printers(server_event_context(), p->msg_ctx);
1728         unbecome_root();
1729
1730         /* some sanity check because you can open a printer or a print server */
1731         /* aka: \\server\printer or \\server */
1732
1733         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1734
1735         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1736         if (!W_ERROR_IS_OK(result)) {
1737                 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1738                         "for printer %s\n", r->in.printername));
1739                 ZERO_STRUCTP(r->out.handle);
1740                 return result;
1741         }
1742
1743         Printer = find_printer_index_by_hnd(p, r->out.handle);
1744         if ( !Printer ) {
1745                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1746                         "handle we created for printer %s\n", r->in.printername));
1747                 close_printer_handle(p, r->out.handle);
1748                 ZERO_STRUCTP(r->out.handle);
1749                 return WERR_INVALID_PARAMETER;
1750         }
1751
1752         /*
1753          * First case: the user is opening the print server:
1754          *
1755          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1756          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1757          *
1758          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1759          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1760          * or if the user is listed in the smb.conf printer admin parameter.
1761          *
1762          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1763          * client view printer folder, but does not show the MSAPW.
1764          *
1765          * Note: this test needs code to check access rights here too. Jeremy
1766          * could you look at this?
1767          *
1768          * Second case: the user is opening a printer:
1769          * NT doesn't let us connect to a printer if the connecting user
1770          * doesn't have print permission.
1771          *
1772          * Third case: user is opening a Port Monitor
1773          * access checks same as opening a handle to the print server.
1774          */
1775
1776         switch (Printer->printer_type )
1777         {
1778         case SPLHND_SERVER:
1779         case SPLHND_PORTMON_TCP:
1780         case SPLHND_PORTMON_LOCAL:
1781                 /* Printserver handles use global struct... */
1782
1783                 snum = -1;
1784
1785                 if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
1786                         r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
1787                         r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
1788                 }
1789
1790                 /* Map standard access rights to object specific access rights */
1791
1792                 se_map_standard(&r->in.access_mask,
1793                                 &printserver_std_mapping);
1794
1795                 /* Deny any object specific bits that don't apply to print
1796                    servers (i.e printer and job specific bits) */
1797
1798                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1799
1800                 if (r->in.access_mask &
1801                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1802                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1803                         close_printer_handle(p, r->out.handle);
1804                         ZERO_STRUCTP(r->out.handle);
1805                         return WERR_ACCESS_DENIED;
1806                 }
1807
1808                 /* Allow admin access */
1809
1810                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1811                 {
1812                         if (!lp_show_add_printer_wizard()) {
1813                                 close_printer_handle(p, r->out.handle);
1814                                 ZERO_STRUCTP(r->out.handle);
1815                                 return WERR_ACCESS_DENIED;
1816                         }
1817
1818                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1819                            and not a printer admin, then fail */
1820
1821                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1822                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1823                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1824                                                 p->session_info->security_token)) {
1825                                 close_printer_handle(p, r->out.handle);
1826                                 ZERO_STRUCTP(r->out.handle);
1827                                 DEBUG(3,("access DENIED as user is not root, "
1828                                         "has no printoperator privilege and is "
1829                                         "not a member of the printoperator builtin group\n"));
1830                                 return WERR_ACCESS_DENIED;
1831                         }
1832
1833                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1834                 }
1835                 else
1836                 {
1837                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1838                 }
1839
1840                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1841                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1842
1843                 /* We fall through to return WERR_OK */
1844                 break;
1845
1846         case SPLHND_PRINTER:
1847                 /* NT doesn't let us connect to a printer if the connecting user
1848                    doesn't have print permission.  */
1849
1850                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1851                         close_printer_handle(p, r->out.handle);
1852                         ZERO_STRUCTP(r->out.handle);
1853                         return WERR_INVALID_HANDLE;
1854                 }
1855
1856                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1857                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1858                 }
1859
1860                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1861
1862                 /* map an empty access mask to the minimum access mask */
1863                 if (r->in.access_mask == 0x0)
1864                         r->in.access_mask = PRINTER_ACCESS_USE;
1865
1866                 /*
1867                  * If we are not serving the printer driver for this printer,
1868                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1869                  * will keep NT clients happy  --jerry
1870                  */
1871
1872                 if (lp_use_client_driver(snum)
1873                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1874                 {
1875                         r->in.access_mask = PRINTER_ACCESS_USE;
1876                 }
1877
1878                 /* check smb.conf parameters and the the sec_desc */
1879                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1880                                                          p->mem_ctx);
1881                 if (raddr == NULL) {
1882                         return WERR_NOT_ENOUGH_MEMORY;
1883                 }
1884
1885                 rc = get_remote_hostname(p->remote_address,
1886                                          &rhost,
1887                                          p->mem_ctx);
1888                 if (rc < 0) {
1889                         return WERR_NOT_ENOUGH_MEMORY;
1890                 }
1891                 if (strequal(rhost, "UNKNOWN")) {
1892                         rhost = raddr;
1893                 }
1894
1895                 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1896                                   rhost, raddr)) {
1897                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1898                         ZERO_STRUCTP(r->out.handle);
1899                         return WERR_ACCESS_DENIED;
1900                 }
1901
1902                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1903                                    p->session_info->security_token, snum) ||
1904                     !W_ERROR_IS_OK(print_access_check(p->session_info,
1905                                                       p->msg_ctx,
1906                                                       snum,
1907                                                       r->in.access_mask))) {
1908                         DEBUG(3, ("access DENIED for printer open\n"));
1909                         close_printer_handle(p, r->out.handle);
1910                         ZERO_STRUCTP(r->out.handle);
1911                         return WERR_ACCESS_DENIED;
1912                 }
1913
1914                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1915                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1916                         close_printer_handle(p, r->out.handle);
1917                         ZERO_STRUCTP(r->out.handle);
1918                         return WERR_ACCESS_DENIED;
1919                 }
1920
1921                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1922                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1923                 else
1924                         r->in.access_mask = PRINTER_ACCESS_USE;
1925
1926                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1927                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1928
1929                 winreg_create_printer_internal(p->mem_ctx,
1930                                       get_session_info_system(),
1931                                       p->msg_ctx,
1932                                       lp_const_servicename(snum));
1933
1934                 break;
1935
1936         default:
1937                 /* sanity check to prevent programmer error */
1938                 ZERO_STRUCTP(r->out.handle);
1939                 return WERR_INVALID_HANDLE;
1940         }
1941
1942         Printer->access_granted = r->in.access_mask;
1943
1944         /*
1945          * If the client sent a devmode in the OpenPrinter() call, then
1946          * save it here in case we get a job submission on this handle
1947          */
1948
1949          if ((Printer->printer_type != SPLHND_SERVER)
1950           && (r->in.devmode_ctr.devmode != NULL)) {
1951                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1952                                 &Printer->devmode);
1953          }
1954
1955         return WERR_OK;
1956 }
1957
1958 /****************************************************************
1959  _spoolss_ClosePrinter
1960 ****************************************************************/
1961
1962 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1963                              struct spoolss_ClosePrinter *r)
1964 {
1965         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1966
1967         if (Printer && Printer->document_started) {
1968                 struct spoolss_EndDocPrinter e;
1969
1970                 e.in.handle = r->in.handle;
1971
1972                 _spoolss_EndDocPrinter(p, &e);
1973         }
1974
1975         if (!close_printer_handle(p, r->in.handle))
1976                 return WERR_INVALID_HANDLE;
1977
1978         /* clear the returned printer handle.  Observed behavior
1979            from Win2k server.  Don't think this really matters.
1980            Previous code just copied the value of the closed
1981            handle.    --jerry */
1982
1983         ZERO_STRUCTP(r->out.handle);
1984
1985         return WERR_OK;
1986 }
1987
1988 /****************************************************************
1989  _spoolss_DeletePrinter
1990 ****************************************************************/
1991
1992 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1993                               struct spoolss_DeletePrinter *r)
1994 {
1995         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1996         WERROR result;
1997         int snum;
1998
1999         if (Printer && Printer->document_started) {
2000                 struct spoolss_EndDocPrinter e;
2001
2002                 e.in.handle = r->in.handle;
2003
2004                 _spoolss_EndDocPrinter(p, &e);
2005         }
2006
2007         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2008                 winreg_delete_printer_key_internal(p->mem_ctx,
2009                                           get_session_info_system(),
2010                                           p->msg_ctx,
2011                                           lp_const_servicename(snum),
2012                                           "");
2013         }
2014
2015         result = delete_printer_handle(p, r->in.handle);
2016
2017         return result;
2018 }
2019
2020 /*******************************************************************
2021  * static function to lookup the version id corresponding to an
2022  * long architecture string
2023  ******************************************************************/
2024
2025 static const struct print_architecture_table_node archi_table[]= {
2026
2027         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2028         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2029         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2030         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2031         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2032         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2033         {"Windows x64",          SPL_ARCH_X64,          3 },
2034         {NULL,                   "",            -1 }
2035 };
2036
2037 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2038                                    SPOOLSS_DRIVER_VERSION_NT35,
2039                                    SPOOLSS_DRIVER_VERSION_NT4,
2040                                    SPOOLSS_DRIVER_VERSION_200X,
2041                                    -1};
2042
2043 static int get_version_id(const char *arch)
2044 {
2045         int i;
2046
2047         for (i=0; archi_table[i].long_archi != NULL; i++)
2048         {
2049                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2050                         return (archi_table[i].version);
2051         }
2052
2053         return -1;
2054 }
2055
2056 /****************************************************************
2057  _spoolss_DeletePrinterDriver
2058 ****************************************************************/
2059
2060 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2061                                     struct spoolss_DeletePrinterDriver *r)
2062 {
2063
2064         struct spoolss_DriverInfo8 *info = NULL;
2065         int                             version;
2066         WERROR                          status;
2067         struct dcerpc_binding_handle *b;
2068         TALLOC_CTX *tmp_ctx = NULL;
2069         int i;
2070         bool found;
2071
2072         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2073            and not a printer admin, then fail */
2074
2075         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2076             !security_token_has_privilege(p->session_info->security_token,
2077                                           SEC_PRIV_PRINT_OPERATOR)) {
2078                 return WERR_ACCESS_DENIED;
2079         }
2080
2081         /* check that we have a valid driver name first */
2082
2083         if ((version = get_version_id(r->in.architecture)) == -1) {
2084                 return WERR_INVALID_ENVIRONMENT;
2085         }
2086
2087         tmp_ctx = talloc_new(p->mem_ctx);
2088         if (!tmp_ctx) {
2089                 return WERR_NOT_ENOUGH_MEMORY;
2090         }
2091
2092         status = winreg_printer_binding_handle(tmp_ctx,
2093                                                get_session_info_system(),
2094                                                p->msg_ctx,
2095                                                &b);
2096         if (!W_ERROR_IS_OK(status)) {
2097                 goto done;
2098         }
2099
2100         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2101                 status = winreg_get_driver(tmp_ctx, b,
2102                                            r->in.architecture, r->in.driver,
2103                                            drv_cversion[i], &info);
2104                 if (!W_ERROR_IS_OK(status)) {
2105                         DEBUG(5, ("skipping del of driver with version %d\n",
2106                                   drv_cversion[i]));
2107                         continue;
2108                 }
2109                 found = true;
2110
2111                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2112                         status = WERR_PRINTER_DRIVER_IN_USE;
2113                         goto done;
2114                 }
2115
2116                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2117                 if (!W_ERROR_IS_OK(status)) {
2118                         DEBUG(0, ("failed del of driver with version %d\n",
2119                                   drv_cversion[i]));
2120                         goto done;
2121                 }
2122         }
2123         if (found == false) {
2124                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2125                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2126         } else {
2127                 status = WERR_OK;
2128         }
2129
2130 done:
2131         talloc_free(tmp_ctx);
2132
2133         return status;
2134 }
2135
2136 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2137                                   struct pipes_struct *p,
2138                                   struct spoolss_DeletePrinterDriverEx *r,
2139                                   struct dcerpc_binding_handle *b,
2140                                   struct spoolss_DriverInfo8 *info)
2141 {
2142         WERROR status;
2143         bool delete_files;
2144
2145         if (printer_driver_in_use(mem_ctx, b, info)) {
2146                 status = WERR_PRINTER_DRIVER_IN_USE;
2147                 goto done;
2148         }
2149
2150         /*
2151          * we have a couple of cases to consider.
2152          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2153          *     then the delete should fail if **any** files overlap with
2154          *     other drivers
2155          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2156          *     non-overlapping files
2157          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2158          *     are set, then do not delete any files
2159          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2160          */
2161
2162         delete_files = r->in.delete_flags
2163                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2164
2165
2166         if (delete_files) {
2167                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2168                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2169                         status = WERR_PRINTER_DRIVER_IN_USE;
2170                         goto done;
2171                 }
2172                 /*
2173                  * printer_driver_files_in_use() has trimmed overlapping files
2174                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2175                  */
2176         }
2177
2178
2179         status = winreg_del_driver(mem_ctx, b, info, info->version);
2180         if (!W_ERROR_IS_OK(status)) {
2181                 goto done;
2182         }
2183
2184         /*
2185          * now delete any associated files if delete_files is
2186          * true. Even if this part failes, we return succes
2187          * because the driver doesn not exist any more
2188          */
2189         if (delete_files) {
2190                 delete_driver_files(p->session_info, info);
2191         }
2192
2193 done:
2194         return status;
2195 }
2196
2197 /****************************************************************
2198  _spoolss_DeletePrinterDriverEx
2199 ****************************************************************/
2200
2201 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2202                                       struct spoolss_DeletePrinterDriverEx *r)
2203 {
2204         struct spoolss_DriverInfo8 *info = NULL;
2205         WERROR                          status;
2206         struct dcerpc_binding_handle *b;
2207         TALLOC_CTX *tmp_ctx = NULL;
2208         int i;
2209         bool found;
2210
2211         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2212            and not a printer admin, then fail */
2213
2214         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2215             !security_token_has_privilege(p->session_info->security_token,
2216                                           SEC_PRIV_PRINT_OPERATOR)) {
2217                 return WERR_ACCESS_DENIED;
2218         }
2219
2220         /* check that we have a valid driver name first */
2221         if (get_version_id(r->in.architecture) == -1) {
2222                 /* this is what NT returns */
2223                 return WERR_INVALID_ENVIRONMENT;
2224         }
2225
2226         tmp_ctx = talloc_new(p->mem_ctx);
2227         if (!tmp_ctx) {
2228                 return WERR_NOT_ENOUGH_MEMORY;
2229         }
2230
2231         status = winreg_printer_binding_handle(tmp_ctx,
2232                                                get_session_info_system(),
2233                                                p->msg_ctx,
2234                                                &b);
2235         if (!W_ERROR_IS_OK(status)) {
2236                 goto done;
2237         }
2238
2239         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2240                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2241                  && (drv_cversion[i] != r->in.version)) {
2242                         continue;
2243                 }
2244
2245                 /* check if a driver with this version exists before delete */
2246                 status = winreg_get_driver(tmp_ctx, b,
2247                                            r->in.architecture, r->in.driver,
2248                                            drv_cversion[i], &info);
2249                 if (!W_ERROR_IS_OK(status)) {
2250                         DEBUG(5, ("skipping del of driver with version %d\n",
2251                                   drv_cversion[i]));
2252                         continue;
2253                 }
2254                 found = true;
2255
2256                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2257                 if (!W_ERROR_IS_OK(status)) {
2258                         DEBUG(0, ("failed to delete driver with version %d\n",
2259                                   drv_cversion[i]));
2260                         goto done;
2261                 }
2262         }
2263         if (found == false) {
2264                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2265                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2266         } else {
2267                 status = WERR_OK;
2268         }
2269
2270 done:
2271         talloc_free(tmp_ctx);
2272         return status;
2273 }
2274
2275
2276 /********************************************************************
2277  GetPrinterData on a printer server Handle.
2278 ********************************************************************/
2279
2280 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2281                                             const char *value,
2282                                             enum winreg_Type *type,
2283                                             union spoolss_PrinterData *data)
2284 {
2285         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2286
2287         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2288                 *type = REG_DWORD;
2289                 SIVAL(&data->value, 0, 0x00);
2290                 return WERR_OK;
2291         }
2292
2293         if (!strcasecmp_m(value, "BeepEnabled")) {
2294                 *type = REG_DWORD;
2295                 SIVAL(&data->value, 0, 0x00);
2296                 return WERR_OK;
2297         }
2298
2299         if (!strcasecmp_m(value, "EventLog")) {
2300                 *type = REG_DWORD;
2301                 /* formally was 0x1b */
2302                 SIVAL(&data->value, 0, 0x00);
2303                 return WERR_OK;
2304         }
2305
2306         if (!strcasecmp_m(value, "NetPopup")) {
2307                 *type = REG_DWORD;
2308                 SIVAL(&data->value, 0, 0x00);
2309                 return WERR_OK;
2310         }
2311
2312         if (!strcasecmp_m(value, "MajorVersion")) {
2313                 *type = REG_DWORD;
2314
2315                 /* Windows NT 4.0 seems to not allow uploading of drivers
2316                    to a server that reports 0x3 as the MajorVersion.
2317                    need to investigate more how Win2k gets around this .
2318                    -- jerry */
2319
2320                 if (RA_WINNT == get_remote_arch()) {
2321                         SIVAL(&data->value, 0, 0x02);
2322                 } else {
2323                         SIVAL(&data->value, 0, 0x03);
2324                 }
2325
2326                 return WERR_OK;
2327         }
2328
2329         if (!strcasecmp_m(value, "MinorVersion")) {
2330                 *type = REG_DWORD;
2331                 SIVAL(&data->value, 0, 0x00);
2332                 return WERR_OK;
2333         }
2334
2335         /* REG_BINARY
2336          *  uint32_t size        = 0x114
2337          *  uint32_t major       = 5
2338          *  uint32_t minor       = [0|1]
2339          *  uint32_t build       = [2195|2600]
2340          *  extra unicode string = e.g. "Service Pack 3"
2341          */
2342         if (!strcasecmp_m(value, "OSVersion")) {
2343                 DATA_BLOB blob;
2344                 enum ndr_err_code ndr_err;
2345                 struct spoolss_OSVersion os;
2346
2347                 os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
2348                                                       "spoolss", "os_major", 5);
2349                                                       /* Windows 2000 == 5.0 */
2350                 os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
2351                                                       "spoolss", "os_minor", 0);
2352                 os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
2353                                                       "spoolss", "os_build", 2195);
2354                 os.extra_string         = "";   /* leave extra string empty */
2355
2356                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2357                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2358                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2359                         return WERR_GEN_FAILURE;
2360                 }
2361
2362                 if (DEBUGLEVEL >= 10) {
2363                         NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2364                 }
2365
2366                 *type = REG_BINARY;
2367                 data->binary = blob;
2368
2369                 return WERR_OK;
2370         }
2371
2372
2373         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2374                 *type = REG_SZ;
2375
2376                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2377                 W_ERROR_HAVE_NO_MEMORY(data->string);
2378
2379                 return WERR_OK;
2380         }
2381
2382         if (!strcasecmp_m(value, "Architecture")) {
2383                 *type = REG_SZ;
2384                 data->string = talloc_strdup(mem_ctx,
2385                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2386                 W_ERROR_HAVE_NO_MEMORY(data->string);
2387
2388                 return WERR_OK;
2389         }
2390
2391         if (!strcasecmp_m(value, "DsPresent")) {
2392                 *type = REG_DWORD;
2393
2394                 /* only show the publish check box if we are a
2395                    member of a AD domain */
2396
2397                 if (lp_security() == SEC_ADS) {
2398                         SIVAL(&data->value, 0, 0x01);
2399                 } else {
2400                         SIVAL(&data->value, 0, 0x00);
2401                 }
2402                 return WERR_OK;
2403         }
2404
2405         if (!strcasecmp_m(value, "DNSMachineName")) {
2406                 const char *hostname = get_mydnsfullname();
2407
2408                 if (!hostname) {
2409                         return WERR_FILE_NOT_FOUND;
2410                 }
2411
2412                 *type = REG_SZ;
2413                 data->string = talloc_strdup(mem_ctx, hostname);
2414                 W_ERROR_HAVE_NO_MEMORY(data->string);
2415
2416                 return WERR_OK;
2417         }
2418
2419         *type = REG_NONE;
2420
2421         return WERR_INVALID_PARAMETER;
2422 }
2423
2424 /****************************************************************
2425  _spoolss_GetPrinterData
2426 ****************************************************************/
2427
2428 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2429                                struct spoolss_GetPrinterData *r)
2430 {
2431         struct spoolss_GetPrinterDataEx r2;
2432
2433         r2.in.handle            = r->in.handle;
2434         r2.in.key_name          = "PrinterDriverData";
2435         r2.in.value_name        = r->in.value_name;
2436         r2.in.offered           = r->in.offered;
2437         r2.out.type             = r->out.type;
2438         r2.out.data             = r->out.data;
2439         r2.out.needed           = r->out.needed;
2440
2441         return _spoolss_GetPrinterDataEx(p, &r2);
2442 }
2443
2444 /*********************************************************
2445  Connect to the client machine.
2446 **********************************************************/
2447
2448 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2449                                       struct sockaddr_storage *client_ss, const char *remote_machine)
2450 {
2451         NTSTATUS ret;
2452         struct sockaddr_storage rm_addr;
2453         char addr[INET6_ADDRSTRLEN];
2454
2455         if ( is_zero_addr(client_ss) ) {
2456                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2457                         remote_machine));
2458                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2459                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2460                         return false;
2461                 }
2462                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2463         } else {
2464                 rm_addr = *client_ss;
2465                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2466                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2467                         addr));
2468         }
2469
2470         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2471                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2472                         addr));
2473                 return false;
2474         }
2475
2476         /* setup the connection */
2477         ret = cli_full_connection( pp_cli, lp_netbios_name(), remote_machine,
2478                 &rm_addr, 0, "IPC$", "IPC",
2479                 "", /* username */
2480                 "", /* domain */
2481                 "", /* password */
2482                 0, lp_client_signing());
2483
2484         if ( !NT_STATUS_IS_OK( ret ) ) {
2485                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2486                         remote_machine ));
2487                 return false;
2488         }
2489
2490         if ( smbXcli_conn_protocol((*pp_cli)->conn) != PROTOCOL_NT1 ) {
2491                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2492                 cli_shutdown(*pp_cli);
2493                 return false;
2494         }
2495
2496         /*
2497          * Ok - we have an anonymous connection to the IPC$ share.
2498          * Now start the NT Domain stuff :-).
2499          */
2500
2501         ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2502         if (!NT_STATUS_IS_OK(ret)) {
2503                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2504                         remote_machine, nt_errstr(ret)));
2505                 cli_shutdown(*pp_cli);
2506                 return false;
2507         }
2508
2509         return true;
2510 }
2511
2512 /***************************************************************************
2513  Connect to the client.
2514 ****************************************************************************/
2515
2516 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2517                                         uint32_t localprinter,
2518                                         enum winreg_Type type,
2519                                         struct policy_handle *handle,
2520                                         struct notify_back_channel **_chan,
2521                                         struct sockaddr_storage *client_ss,
2522                                         struct messaging_context *msg_ctx)
2523 {
2524         WERROR result;
2525         NTSTATUS status;
2526         struct notify_back_channel *chan;
2527
2528         for (chan = back_channels; chan; chan = chan->next) {
2529                 if (memcmp(&chan->client_address, client_ss,
2530                            sizeof(struct sockaddr_storage)) == 0) {
2531                         break;
2532                 }
2533         }
2534
2535         /*
2536          * If it's the first connection, contact the client
2537          * and connect to the IPC$ share anonymously
2538          */
2539         if (!chan) {
2540                 fstring unix_printer;
2541
2542                 /* the +2 is to strip the leading 2 backslashs */
2543                 fstrcpy(unix_printer, printer + 2);
2544
2545                 chan = talloc_zero(NULL, struct notify_back_channel);
2546                 if (!chan) {
2547                         return false;
2548                 }
2549                 chan->client_address = *client_ss;
2550
2551                 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2552                         TALLOC_FREE(chan);
2553                         return false;
2554                 }
2555
2556                 DLIST_ADD(back_channels, chan);
2557
2558                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2559                                    receive_notify2_message_list);
2560         }
2561
2562         if (chan->cli_pipe == NULL ||
2563             chan->cli_pipe->binding_handle == NULL) {
2564                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2565                         "NULL %s for printer %s\n",
2566                         chan->cli_pipe == NULL ?
2567                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2568                         printer));
2569                 return false;
2570         }
2571
2572         /*
2573          * Tell the specific printing tdb we want messages for this printer
2574          * by registering our PID.
2575          */
2576
2577         if (!print_notify_register_pid(snum)) {
2578                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2579                           printer));
2580         }
2581
2582         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2583                                                  talloc_tos(),
2584                                                  printer,
2585                                                  localprinter,
2586                                                  type,
2587                                                  0,
2588                                                  NULL,
2589                                                  handle,
2590                                                  &result);
2591         if (!NT_STATUS_IS_OK(status)) {
2592                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2593                 result = ntstatus_to_werror(status);
2594         } else if (!W_ERROR_IS_OK(result)) {
2595                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2596         }
2597
2598         chan->active_connections++;
2599         *_chan = chan;
2600
2601         return (W_ERROR_IS_OK(result));
2602 }
2603
2604 /****************************************************************
2605  ****************************************************************/
2606
2607 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2608                                                              const struct spoolss_NotifyOption *r)
2609 {
2610         struct spoolss_NotifyOption *option;
2611         uint32_t i,k;
2612
2613         if (!r) {
2614                 return NULL;
2615         }
2616
2617         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2618         if (!option) {
2619                 return NULL;
2620         }
2621
2622         *option = *r;
2623
2624         if (!option->count) {
2625                 return option;
2626         }
2627
2628         option->types = talloc_zero_array(option,
2629                 struct spoolss_NotifyOptionType, option->count);
2630         if (!option->types) {
2631                 talloc_free(option);
2632                 return NULL;
2633         }
2634
2635         for (i=0; i < option->count; i++) {
2636                 option->types[i] = r->types[i];
2637
2638                 if (option->types[i].count) {
2639                         option->types[i].fields = talloc_zero_array(option,
2640                                 union spoolss_Field, option->types[i].count);
2641                         if (!option->types[i].fields) {
2642                                 talloc_free(option);
2643                                 return NULL;
2644                         }
2645                         for (k=0; k<option->types[i].count; k++) {
2646                                 option->types[i].fields[k] =
2647                                         r->types[i].fields[k];
2648                         }
2649                 }
2650         }
2651
2652         return option;
2653 }
2654
2655 /****************************************************************
2656  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2657  *
2658  * before replying OK: status=0 a rpc call is made to the workstation
2659  * asking ReplyOpenPrinter
2660  *
2661  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2662  * called from api_spoolss_rffpcnex
2663 ****************************************************************/
2664
2665 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2666                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2667 {
2668         int snum = -1;
2669         struct spoolss_NotifyOption *option = r->in.notify_options;
2670         struct sockaddr_storage client_ss;
2671         ssize_t client_len;
2672
2673         /* store the notify value in the printer struct */
2674
2675         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2676
2677         if (!Printer) {
2678                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2679                         "Invalid handle (%s:%u:%u).\n",
2680                         OUR_HANDLE(r->in.handle)));
2681                 return WERR_INVALID_HANDLE;
2682         }
2683
2684         Printer->notify.flags           = r->in.flags;
2685         Printer->notify.options         = r->in.options;
2686         Printer->notify.printerlocal    = r->in.printer_local;
2687         Printer->notify.msg_ctx         = p->msg_ctx;
2688
2689         TALLOC_FREE(Printer->notify.option);
2690         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2691
2692         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2693
2694         /* Connect to the client machine and send a ReplyOpenPrinter */
2695
2696         if ( Printer->printer_type == SPLHND_SERVER)
2697                 snum = -1;
2698         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2699                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2700                 return WERR_INVALID_HANDLE;
2701
2702         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2703                   "remote_address is %s\n",
2704                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2705
2706         if (!lp_print_notify_backchannel(snum)) {
2707                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2708                         "backchannel disabled\n"));
2709                 return WERR_RPC_S_SERVER_UNAVAILABLE;
2710         }
2711
2712         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2713                                                   (struct sockaddr *) &client_ss,
2714                                                   sizeof(struct sockaddr_storage));
2715         if (client_len < 0) {
2716                 return WERR_NOT_ENOUGH_MEMORY;
2717         }
2718
2719         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2720                                         Printer->notify.printerlocal, REG_SZ,
2721                                         &Printer->notify.cli_hnd,
2722                                         &Printer->notify.cli_chan,
2723                                         &client_ss, p->msg_ctx)) {
2724                 return WERR_RPC_S_SERVER_UNAVAILABLE;
2725         }
2726
2727         return WERR_OK;
2728 }
2729
2730 /*******************************************************************
2731  * fill a notify_info_data with the servername
2732  ********************************************************************/
2733
2734 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2735                                        int snum,
2736                                        struct spoolss_Notify *data,
2737                                        print_queue_struct *queue,
2738                                        struct spoolss_PrinterInfo2 *pinfo2,
2739                                        TALLOC_CTX *mem_ctx)
2740 {
2741         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2742 }
2743
2744 /*******************************************************************
2745  * fill a notify_info_data with the printername (not including the servername).
2746  ********************************************************************/
2747
2748 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2749                                         int snum,
2750                                         struct spoolss_Notify *data,
2751                                         print_queue_struct *queue,
2752                                         struct spoolss_PrinterInfo2 *pinfo2,
2753                                         TALLOC_CTX *mem_ctx)
2754 {
2755         /* the notify name should not contain the \\server\ part */
2756         const char *p = strrchr(pinfo2->printername, '\\');
2757
2758         if (!p) {
2759                 p = pinfo2->printername;
2760         } else {
2761                 p++;
2762         }
2763
2764         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2765 }
2766
2767 /*******************************************************************
2768  * fill a notify_info_data with the servicename
2769  ********************************************************************/
2770
2771 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2772                                       int snum,
2773                                       struct spoolss_Notify *data,
2774                                       print_queue_struct *queue,
2775                                       struct spoolss_PrinterInfo2 *pinfo2,
2776                                       TALLOC_CTX *mem_ctx)
2777 {
2778         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2779 }
2780
2781 /*******************************************************************
2782  * fill a notify_info_data with the port name
2783  ********************************************************************/
2784
2785 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2786                                      int snum,
2787                                      struct spoolss_Notify *data,
2788                                      print_queue_struct *queue,
2789                                      struct spoolss_PrinterInfo2 *pinfo2,
2790                                      TALLOC_CTX *mem_ctx)
2791 {
2792         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2793 }
2794
2795 /*******************************************************************
2796  * fill a notify_info_data with the printername
2797  * but it doesn't exist, have to see what to do
2798  ********************************************************************/
2799
2800 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2801                                        int snum,
2802                                        struct spoolss_Notify *data,
2803                                        print_queue_struct *queue,
2804                                        struct spoolss_PrinterInfo2 *pinfo2,
2805                                        TALLOC_CTX *mem_ctx)
2806 {
2807         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2808 }
2809
2810 /*******************************************************************
2811  * fill a notify_info_data with the comment
2812  ********************************************************************/
2813
2814 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2815                                    int snum,
2816                                    struct spoolss_Notify *data,
2817                                    print_queue_struct *queue,
2818                                    struct spoolss_PrinterInfo2 *pinfo2,
2819                                    TALLOC_CTX *mem_ctx)
2820 {
2821         const char *p;
2822
2823         if (*pinfo2->comment == '\0') {
2824                 p = lp_comment(talloc_tos(), snum);
2825         } else {
2826                 p = pinfo2->comment;
2827         }
2828
2829         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2830 }
2831
2832 /*******************************************************************
2833  * fill a notify_info_data with the comment
2834  * location = "Room 1, floor 2, building 3"
2835  ********************************************************************/
2836
2837 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2838                                     int snum,
2839                                     struct spoolss_Notify *data,
2840                                     print_queue_struct *queue,
2841                                     struct spoolss_PrinterInfo2 *pinfo2,
2842                                     TALLOC_CTX *mem_ctx)
2843 {
2844         const char *loc = pinfo2->location;
2845         NTSTATUS status;
2846
2847         status = printer_list_get_printer(mem_ctx,
2848                                           pinfo2->sharename,
2849                                           NULL,
2850                                           &loc,
2851                                           NULL);
2852         if (NT_STATUS_IS_OK(status)) {
2853                 if (loc == NULL) {
2854                         loc = pinfo2->location;
2855                 }
2856         }
2857
2858         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2859 }
2860
2861 /*******************************************************************
2862  * fill a notify_info_data with the device mode
2863  * jfm:xxxx don't to it for know but that's a real problem !!!
2864  ********************************************************************/
2865
2866 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2867                                    int snum,
2868                                    struct spoolss_Notify *data,
2869                                    print_queue_struct *queue,
2870                                    struct spoolss_PrinterInfo2 *pinfo2,
2871                                    TALLOC_CTX *mem_ctx)
2872 {
2873         /* for a dummy implementation we have to zero the fields */
2874         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2875 }
2876
2877 /*******************************************************************
2878  * fill a notify_info_data with the separator file name
2879  ********************************************************************/
2880
2881 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2882                                    int snum,
2883                                    struct spoolss_Notify *data,
2884                                    print_queue_struct *queue,
2885                                    struct spoolss_PrinterInfo2 *pinfo2,
2886                                    TALLOC_CTX *mem_ctx)
2887 {
2888         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2889 }
2890
2891 /*******************************************************************
2892  * fill a notify_info_data with the print processor
2893  * jfm:xxxx return always winprint to indicate we don't do anything to it
2894  ********************************************************************/
2895
2896 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2897                                            int snum,
2898                                            struct spoolss_Notify *data,
2899                                            print_queue_struct *queue,
2900                                            struct spoolss_PrinterInfo2 *pinfo2,
2901                                            TALLOC_CTX *mem_ctx)
2902 {
2903         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2904 }
2905
2906 /*******************************************************************
2907  * fill a notify_info_data with the print processor options
2908  * jfm:xxxx send an empty string
2909  ********************************************************************/
2910
2911 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2912                                       int snum,
2913                                       struct spoolss_Notify *data,
2914                                       print_queue_struct *queue,
2915                                       struct spoolss_PrinterInfo2 *pinfo2,
2916                                       TALLOC_CTX *mem_ctx)
2917 {
2918         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2919 }
2920
2921 /*******************************************************************
2922  * fill a notify_info_data with the data type
2923  * jfm:xxxx always send RAW as data type
2924  ********************************************************************/
2925
2926 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2927                                     int snum,
2928                                     struct spoolss_Notify *data,
2929                                     print_queue_struct *queue,
2930                                     struct spoolss_PrinterInfo2 *pinfo2,
2931                                     TALLOC_CTX *mem_ctx)
2932 {
2933         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2934 }
2935
2936 /*******************************************************************
2937  * fill a notify_info_data with the security descriptor
2938  * jfm:xxxx send an null pointer to say no security desc
2939  * have to implement security before !
2940  ********************************************************************/
2941
2942 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2943                                          int snum,
2944                                          struct spoolss_Notify *data,
2945                                          print_queue_struct *queue,
2946                                          struct spoolss_PrinterInfo2 *pinfo2,
2947                                          TALLOC_CTX *mem_ctx)
2948 {
2949         if (pinfo2->secdesc == NULL) {
2950                 data->data.sd.sd = NULL;
2951         } else {
2952                 data->data.sd.sd = security_descriptor_copy(mem_ctx,
2953                                                             pinfo2->secdesc);
2954         }
2955         data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2956                                                              0);
2957 }
2958
2959 /*******************************************************************
2960  * fill a notify_info_data with the attributes
2961  * jfm:xxxx a samba printer is always shared
2962  ********************************************************************/
2963
2964 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2965                                       int snum,
2966                                       struct spoolss_Notify *data,
2967                                       print_queue_struct *queue,
2968                                       struct spoolss_PrinterInfo2 *pinfo2,
2969                                       TALLOC_CTX *mem_ctx)
2970 {
2971         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2972 }
2973
2974 /*******************************************************************
2975  * fill a notify_info_data with the priority
2976  ********************************************************************/
2977
2978 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2979                                     int snum,
2980                                     struct spoolss_Notify *data,
2981                                     print_queue_struct *queue,
2982                                     struct spoolss_PrinterInfo2 *pinfo2,
2983                                     TALLOC_CTX *mem_ctx)
2984 {
2985         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2986 }
2987
2988 /*******************************************************************
2989  * fill a notify_info_data with the default priority
2990  ********************************************************************/
2991
2992 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2993                                             int snum,
2994                                             struct spoolss_Notify *data,
2995                                             print_queue_struct *queue,
2996                                             struct spoolss_PrinterInfo2 *pinfo2,
2997                                             TALLOC_CTX *mem_ctx)
2998 {
2999         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3000 }
3001
3002 /*******************************************************************
3003  * fill a notify_info_data with the start time
3004  ********************************************************************/
3005
3006 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3007                                       int snum,
3008                                       struct spoolss_Notify *data,
3009                                       print_queue_struct *queue,
3010                                       struct spoolss_PrinterInfo2 *pinfo2,
3011                                       TALLOC_CTX *mem_ctx)
3012 {
3013         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3014 }
3015
3016 /*******************************************************************
3017  * fill a notify_info_data with the until time
3018  ********************************************************************/
3019
3020 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3021                                       int snum,
3022                                       struct spoolss_Notify *data,
3023                                       print_queue_struct *queue,
3024                                       struct spoolss_PrinterInfo2 *pinfo2,
3025                                       TALLOC_CTX *mem_ctx)
3026 {
3027         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3028 }
3029
3030 /*******************************************************************
3031  * fill a notify_info_data with the status
3032  ********************************************************************/
3033
3034 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3035                                   int snum,
3036                                   struct spoolss_Notify *data,
3037                                   print_queue_struct *queue,
3038                                   struct spoolss_PrinterInfo2 *pinfo2,
3039                                   TALLOC_CTX *mem_ctx)
3040 {
3041         print_status_struct status;
3042
3043         print_queue_length(msg_ctx, snum, &status);
3044         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3045 }
3046
3047 /*******************************************************************
3048  * fill a notify_info_data with the number of jobs queued
3049  ********************************************************************/
3050
3051 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3052                                  int snum,
3053                                  struct spoolss_Notify *data,
3054                                  print_queue_struct *queue,
3055                                  struct spoolss_PrinterInfo2 *pinfo2,
3056                                  TALLOC_CTX *mem_ctx)
3057 {
3058         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3059                 data, print_queue_length(msg_ctx, snum, NULL));
3060 }
3061
3062 /*******************************************************************
3063  * fill a notify_info_data with the average ppm
3064  ********************************************************************/
3065
3066 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3067                                        int snum,
3068                                        struct spoolss_Notify *data,
3069                                        print_queue_struct *queue,
3070                                        struct spoolss_PrinterInfo2 *pinfo2,
3071                                        TALLOC_CTX *mem_ctx)
3072 {
3073         /* always respond 8 pages per minutes */
3074         /* a little hard ! */
3075         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3076 }
3077
3078 /*******************************************************************
3079  * fill a notify_info_data with username
3080  ********************************************************************/
3081
3082 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3083                                     int snum,
3084                                     struct spoolss_Notify *data,
3085                                     print_queue_struct *queue,
3086                                     struct spoolss_PrinterInfo2 *pinfo2,
3087                                     TALLOC_CTX *mem_ctx)
3088 {
3089         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3090 }
3091
3092 /*******************************************************************
3093  * fill a notify_info_data with job status
3094  ********************************************************************/
3095
3096 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3097                                       int snum,
3098                                       struct spoolss_Notify *data,
3099                                       print_queue_struct *queue,
3100                                       struct spoolss_PrinterInfo2 *pinfo2,
3101                                       TALLOC_CTX *mem_ctx)
3102 {
3103         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3104 }
3105
3106 /*******************************************************************
3107  * fill a notify_info_data with job name
3108  ********************************************************************/
3109
3110 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3111                                     int snum,
3112                                     struct spoolss_Notify *data,
3113                                     print_queue_struct *queue,
3114                                     struct spoolss_PrinterInfo2 *pinfo2,
3115                                     TALLOC_CTX *mem_ctx)
3116 {
3117         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3118 }
3119
3120 /*******************************************************************
3121  * fill a notify_info_data with job status
3122  ********************************************************************/
3123
3124 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3125                                              int snum,
3126                                              struct spoolss_Notify *data,
3127                                              print_queue_struct *queue,
3128                                              struct spoolss_PrinterInfo2 *pinfo2,
3129                                              TALLOC_CTX *mem_ctx)
3130 {
3131         /*
3132          * Now we're returning job status codes we just return a "" here. JRA.
3133          */
3134
3135         const char *p = "";
3136
3137 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3138         p = "unknown";
3139
3140         switch (queue->status) {
3141         case LPQ_QUEUED:
3142                 p = "Queued";
3143                 break;
3144         case LPQ_PAUSED:
3145                 p = "";    /* NT provides the paused string */
3146                 break;
3147         case LPQ_SPOOLING:
3148                 p = "Spooling";
3149                 break;
3150         case LPQ_PRINTING:
3151                 p = "Printing";
3152                 break;
3153         }
3154 #endif /* NO LONGER NEEDED. */
3155
3156         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3157 }
3158
3159 /*******************************************************************
3160  * fill a notify_info_data with job time
3161  ********************************************************************/
3162
3163 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3164                                     int snum,
3165                                     struct spoolss_Notify *data,
3166                                     print_queue_struct *queue,
3167                                     struct spoolss_PrinterInfo2 *pinfo2,
3168                                     TALLOC_CTX *mem_ctx)
3169 {
3170         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3171 }
3172
3173 /*******************************************************************
3174  * fill a notify_info_data with job size
3175  ********************************************************************/
3176
3177 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3178                                     int snum,
3179                                     struct spoolss_Notify *data,
3180                                     print_queue_struct *queue,
3181                                     struct spoolss_PrinterInfo2 *pinfo2,
3182                                     TALLOC_CTX *mem_ctx)
3183 {
3184         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3185 }
3186
3187 /*******************************************************************
3188  * fill a notify_info_data with page info
3189  ********************************************************************/
3190 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3191                                        int snum,
3192                                 struct spoolss_Notify *data,
3193                                 print_queue_struct *queue,
3194                                 struct spoolss_PrinterInfo2 *pinfo2,
3195                                 TALLOC_CTX *mem_ctx)
3196 {
3197         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3198 }
3199
3200 /*******************************************************************
3201  * fill a notify_info_data with pages printed info.
3202  ********************************************************************/
3203 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3204                                          int snum,
3205                                 struct spoolss_Notify *data,
3206                                 print_queue_struct *queue,
3207                                 struct spoolss_PrinterInfo2 *pinfo2,
3208                                 TALLOC_CTX *mem_ctx)
3209 {
3210         /* Add code when back-end tracks this */
3211         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3212 }
3213
3214 /*******************************************************************
3215  Fill a notify_info_data with job position.
3216  ********************************************************************/
3217
3218 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3219                                         int snum,
3220                                         struct spoolss_Notify *data,
3221                                         print_queue_struct *queue,
3222                                         struct spoolss_PrinterInfo2 *pinfo2,
3223                                         TALLOC_CTX *mem_ctx)
3224 {
3225         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3226 }
3227
3228 /*******************************************************************
3229  Fill a notify_info_data with submitted time.
3230  ********************************************************************/
3231
3232 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3233                                           int snum,
3234                                           struct spoolss_Notify *data,
3235                                           print_queue_struct *queue,
3236                                           struct spoolss_PrinterInfo2 *pinfo2,
3237                                           TALLOC_CTX *mem_ctx)
3238 {
3239         data->data.string.string = NULL;
3240         data->data.string.size = 0;
3241
3242         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3243                                &data->data.string.string,
3244                                &data->data.string.size);
3245
3246 }
3247
3248 struct s_notify_info_data_table
3249 {
3250         enum spoolss_NotifyType type;
3251         uint16_t field;
3252         const char *name;
3253         enum spoolss_NotifyTable variable_type;
3254         void (*fn) (struct messaging_context *msg_ctx,
3255                     int snum, struct spoolss_Notify *data,
3256                     print_queue_struct *queue,
3257                     struct spoolss_PrinterInfo2 *pinfo2,
3258                     TALLOC_CTX *mem_ctx);
3259 };
3260
3261 /* A table describing the various print notification constants and
3262    whether the notification data is a pointer to a variable sized
3263    buffer, a one value uint32_t or a two value uint32_t. */
3264
3265 static const struct s_notify_info_data_table notify_info_data_table[] =
3266 {
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3293 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3294 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3295 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3296 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3301 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3302 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3304 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3305 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3306 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3307 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3308 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3309 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3311 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3313 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3314 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3315 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3316 };
3317
3318 /*******************************************************************
3319  Return the variable_type of info_data structure.
3320 ********************************************************************/
3321
3322 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3323                                                                   uint16_t field)
3324 {
3325         int i=0;
3326
3327         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3328                 if ( (notify_info_data_table[i].type == type) &&
3329                      (notify_info_data_table[i].field == field) ) {
3330                         return notify_info_data_table[i].variable_type;
3331                 }
3332         }
3333
3334         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3335
3336         return (enum spoolss_NotifyTable) 0;
3337 }
3338
3339 /****************************************************************************
3340 ****************************************************************************/
3341
3342 static bool search_notify(enum spoolss_NotifyType type,
3343                           uint16_t field,
3344                           int *value)
3345 {
3346         int i;
3347
3348         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3349                 if (notify_info_data_table[i].type == type &&
3350                     notify_info_data_table[i].field == field &&
3351                     notify_info_data_table[i].fn != NULL) {
3352                         *value = i;
3353                         return true;
3354                 }
3355         }
3356
3357         return false;
3358 }
3359
3360 /****************************************************************************
3361 ****************************************************************************/
3362
3363 static void construct_info_data(struct spoolss_Notify *info_data,
3364                                 enum spoolss_NotifyType type,
3365                                 uint16_t field, int id)
3366 {
3367         info_data->type                 = type;
3368         info_data->field.field          = field;
3369         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3370         info_data->job_id               = id;
3371 }
3372
3373 /*******************************************************************
3374  *
3375  * fill a notify_info struct with info asked
3376  *
3377  ********************************************************************/
3378
3379 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3380                                           struct printer_handle *print_hnd,
3381                                           struct spoolss_NotifyInfo *info,
3382                                           struct spoolss_PrinterInfo2 *pinfo2,
3383                                           int snum,
3384                                           const struct spoolss_NotifyOptionType *option_type,
3385                                           uint32_t id,
3386                                           TALLOC_CTX *mem_ctx)
3387 {
3388         int field_num,j;
3389         enum spoolss_NotifyType type;
3390         uint16_t field;
3391
3392         struct spoolss_Notify *current_data;
3393
3394         type = option_type->type;
3395
3396         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3397                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3398                 option_type->count, lp_servicename(talloc_tos(), snum)));
3399
3400         for(field_num=0; field_num < option_type->count; field_num++) {
3401                 field = option_type->fields[field_num].field;
3402
3403                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3404
3405                 if (!search_notify(type, field, &j) )
3406                         continue;
3407
3408                 info->notifies = talloc_realloc(info, info->notifies,
3409                                                       struct spoolss_Notify,
3410                                                       info->count + 1);
3411                 if (info->notifies == NULL) {
3412                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3413                         return false;
3414                 }
3415
3416                 current_data = &info->notifies[info->count];
3417
3418                 construct_info_data(current_data, type, field, id);
3419
3420                 DEBUG(10, ("construct_notify_printer_info: "
3421                            "calling [%s]  snum=%d  printername=[%s])\n",
3422                            notify_info_data_table[j].name, snum,
3423                            pinfo2->printername));
3424
3425                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3426                                              NULL, pinfo2, mem_ctx);
3427
3428                 info->count++;
3429         }
3430
3431         return true;
3432 }
3433
3434 /*******************************************************************
3435  *
3436  * fill a notify_info struct with info asked
3437  *
3438  ********************************************************************/
3439
3440 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3441                                        print_queue_struct *queue,
3442                                        struct spoolss_NotifyInfo *info,
3443                                        struct spoolss_PrinterInfo2 *pinfo2,
3444                                        int snum,
3445                                        const struct spoolss_NotifyOptionType *option_type,
3446                                        uint32_t id,
3447                                        TALLOC_CTX *mem_ctx)
3448 {
3449         int field_num,j;
3450         enum spoolss_NotifyType type;
3451         uint16_t field;
3452         struct spoolss_Notify *current_data;
3453
3454         DEBUG(4,("construct_notify_jobs_info\n"));
3455
3456         type = option_type->type;
3457
3458         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3459                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3460                 option_type->count));
3461
3462         for(field_num=0; field_num<option_type->count; field_num++) {
3463                 field = option_type->fields[field_num].field;
3464
3465                 if (!search_notify(type, field, &j) )
3466                         continue;
3467
3468                 info->notifies = talloc_realloc(info, info->notifies,
3469                                                       struct spoolss_Notify,
3470                                                       info->count + 1);
3471                 if (info->notifies == NULL) {
3472                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3473                         return false;
3474                 }
3475
3476                 current_data=&(info->notifies[info->count]);
3477
3478                 construct_info_data(current_data, type, field, id);
3479                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3480                                              queue, pinfo2, mem_ctx);
3481                 info->count++;
3482         }
3483
3484         return true;
3485 }
3486
3487 /*
3488  * JFM: The enumeration is not that simple, it's even non obvious.
3489  *
3490  * let's take an example: I want to monitor the PRINTER SERVER for
3491  * the printer's name and the number of jobs currently queued.
3492  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3493  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3494  *
3495  * I have 3 printers on the back of my server.
3496  *
3497  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3498  * structures.
3499  *   Number     Data                    Id
3500  *      1       printer 1 name          1
3501  *      2       printer 1 cjob          1
3502  *      3       printer 2 name          2
3503  *      4       printer 2 cjob          2
3504  *      5       printer 3 name          3
3505  *      6       printer 3 name          3
3506  *
3507  * that's the print server case, the printer case is even worse.
3508  */
3509
3510 /*******************************************************************
3511  *
3512  * enumerate all printers on the printserver
3513  * fill a notify_info struct with info asked
3514  *
3515  ********************************************************************/
3516
3517 static WERROR printserver_notify_info(struct pipes_struct *p,
3518                                       struct policy_handle *hnd,
3519                                       struct spoolss_NotifyInfo *info,
3520                                       TALLOC_CTX *mem_ctx)
3521 {
3522         int snum;
3523         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3524         int n_services=lp_numservices();
3525         int i;
3526         struct spoolss_NotifyOption *option;
3527         struct spoolss_NotifyOptionType option_type;
3528         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3529         WERROR result;
3530
3531         DEBUG(4,("printserver_notify_info\n"));
3532
3533         if (!Printer)
3534                 return WERR_INVALID_HANDLE;
3535
3536         option = Printer->notify.option;
3537
3538         info->version   = 2;
3539         info->notifies  = NULL;
3540         info->count     = 0;
3541
3542         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3543            sending a ffpcn() request first */
3544
3545         if ( !option )
3546                 return WERR_INVALID_HANDLE;
3547
3548         for (i=0; i<option->count; i++) {
3549                 option_type = option->types[i];
3550
3551                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3552                         continue;
3553
3554                 for (snum = 0; snum < n_services; snum++) {
3555                         if (!lp_browseable(snum) ||
3556                             !lp_snum_ok(snum) ||
3557                             !lp_printable(snum)) {
3558                                 continue; /* skip */
3559                         }
3560
3561                         /* Maybe we should use the SYSTEM session_info here... */
3562                         result = winreg_get_printer_internal(mem_ctx,
3563                                                     get_session_info_system(),
3564                                                     p->msg_ctx,
3565                                                     lp_servicename(talloc_tos(), snum),
3566                                                     &pinfo2);
3567                         if (!W_ERROR_IS_OK(result)) {
3568                                 DEBUG(4, ("printserver_notify_info: "
3569                                           "Failed to get printer [%s]\n",
3570                                           lp_servicename(talloc_tos(), snum)));
3571                                 continue;
3572                         }
3573
3574
3575                         construct_notify_printer_info(p->msg_ctx,
3576                                                       Printer, info,
3577                                                       pinfo2, snum,
3578                                                       &option_type, snum,
3579                                                       mem_ctx);
3580
3581                         TALLOC_FREE(pinfo2);
3582                 }
3583         }
3584
3585 #if 0
3586         /*
3587          * Debugging information, don't delete.
3588          */
3589
3590         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3591         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3592         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3593
3594         for (i=0; i<info->count; i++) {
3595                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3596                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3597                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3598         }
3599 #endif
3600
3601         return WERR_OK;
3602 }
3603
3604 /*******************************************************************
3605  *
3606  * fill a notify_info struct with info asked
3607  *
3608  ********************************************************************/
3609
3610 static WERROR printer_notify_info(struct pipes_struct *p,
3611                                   struct policy_handle *hnd,
3612                                   struct spoolss_NotifyInfo *info,
3613                                   TALLOC_CTX *mem_ctx)
3614 {
3615         int snum;
3616         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3617         int i;
3618         uint32_t id;
3619         struct spoolss_NotifyOption *option;
3620         struct spoolss_NotifyOptionType option_type;
3621         int count,j;
3622         print_queue_struct *queue=NULL;
3623         print_status_struct status;
3624         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3625         WERROR result;
3626         struct tdb_print_db *pdb;
3627
3628         DEBUG(4,("printer_notify_info\n"));
3629
3630         if (!Printer)
3631                 return WERR_INVALID_HANDLE;
3632
3633         option = Printer->notify.option;
3634         id = 0x0;
3635
3636         info->version   = 2;
3637         info->notifies  = NULL;
3638         info->count     = 0;
3639
3640         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3641            sending a ffpcn() request first */
3642
3643         if ( !option )
3644                 return WERR_INVALID_HANDLE;
3645
3646         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3647                 return WERR_INVALID_HANDLE;
3648         }
3649
3650         pdb = get_print_db_byname(Printer->sharename);
3651         if (pdb == NULL) {
3652                 return WERR_INVALID_HANDLE;
3653         }
3654
3655         /* Maybe we should use the SYSTEM session_info here... */
3656         result = winreg_get_printer_internal(mem_ctx,
3657                                     get_session_info_system(),
3658                                     p->msg_ctx,
3659                                     lp_servicename(talloc_tos(), snum), &pinfo2);
3660         if (!W_ERROR_IS_OK(result)) {
3661                 result = WERR_INVALID_HANDLE;
3662                 goto err_pdb_drop;
3663         }
3664
3665         /*
3666          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3667          * correct servername.
3668          */
3669         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3670         if (pinfo2->servername == NULL) {
3671                 result = WERR_NOT_ENOUGH_MEMORY;
3672                 goto err_pdb_drop;
3673         }
3674
3675         for (i = 0; i < option->count; i++) {
3676                 option_type = option->types[i];
3677
3678                 switch (option_type.type) {
3679                 case PRINTER_NOTIFY_TYPE:
3680                         if (construct_notify_printer_info(p->msg_ctx,
3681                                                           Printer, info,
3682                                                           pinfo2, snum,
3683                                                           &option_type, id,
3684                                                           mem_ctx)) {
3685                                 id--;
3686                         }
3687                         break;
3688
3689                 case JOB_NOTIFY_TYPE:
3690
3691                         count = print_queue_status(p->msg_ctx, snum, &queue,
3692                                                    &status);
3693
3694                         for (j = 0; j < count; j++) {
3695                                 uint32_t jobid;
3696                                 jobid = sysjob_to_jobid_pdb(pdb,
3697                                                             queue[j].sysjob);
3698                                 if (jobid == (uint32_t)-1) {
3699                                         DEBUG(2, ("ignoring untracked job %d\n",
3700                                                   queue[j].sysjob));
3701                                         continue;
3702                                 }
3703                                 /* FIXME check return value */
3704                                 construct_notify_jobs_info(p->msg_ctx,
3705                                                            &queue[j], info,
3706                                                            pinfo2, snum,
3707                                                            &option_type,
3708                                                            jobid,
3709                                                            mem_ctx);
3710                         }
3711
3712                         SAFE_FREE(queue);
3713                         break;
3714                 }
3715         }
3716
3717         /*
3718          * Debugging information, don't delete.
3719          */
3720         /*
3721         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3722         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3723         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3724
3725         for (i=0; i<info->count; i++) {
3726                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3727                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3728                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3729         }
3730         */
3731
3732         talloc_free(pinfo2);
3733         result = WERR_OK;
3734 err_pdb_drop:
3735         release_print_db(pdb);
3736         return result;
3737 }
3738
3739 /****************************************************************
3740  _spoolss_RouterRefreshPrinterChangeNotify
3741 ****************************************************************/
3742
3743 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3744                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3745 {
3746         struct spoolss_NotifyInfo *info;
3747
3748         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3749         WERROR result = WERR_INVALID_HANDLE;
3750
3751         /* we always have a spoolss_NotifyInfo struct */
3752         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3753         if (!info) {
3754                 result = WERR_NOT_ENOUGH_MEMORY;
3755                 goto done;
3756         }
3757
3758         *r->out.info = info;
3759
3760         if (!Printer) {
3761                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3762                         "Invalid handle (%s:%u:%u).\n",
3763                         OUR_HANDLE(r->in.handle)));
3764                 goto done;
3765         }
3766
3767         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3768
3769         /*
3770          *      We are now using the change value, and
3771          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3772          *      I don't have a global notification system, I'm sending back all the
3773          *      information even when _NOTHING_ has changed.
3774          */
3775
3776         /* We need to keep track of the change value to send back in
3777            RRPCN replies otherwise our updates are ignored. */
3778
3779         Printer->notify.fnpcn = true;
3780
3781         if (Printer->notify.cli_chan != NULL &&
3782             Printer->notify.cli_chan->active_connections > 0) {
3783                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3784                         "Saving change value in request [%x]\n",
3785                         r->in.change_low));
3786                 Printer->notify.change = r->in.change_low;
3787         }
3788
3789         /* just ignore the spoolss_NotifyOption */
3790
3791         switch (Printer->printer_type) {
3792                 case SPLHND_SERVER:
3793                         result = printserver_notify_info(p, r->in.handle,
3794                                                          info, p->mem_ctx);
3795                         break;
3796
3797                 case SPLHND_PRINTER:
3798                         result = printer_notify_info(p, r->in.handle,
3799                                                      info, p->mem_ctx);
3800                         break;
3801         }
3802
3803         Printer->notify.fnpcn = false;
3804
3805 done:
3806         return result;
3807 }
3808
3809 /********************************************************************
3810  ********************************************************************/
3811
3812 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3813                                  const char *servername,
3814                                  const char *printername,
3815                                  const char **printername_p)
3816 {
3817         /* FIXME: add lp_force_printername() */
3818
3819         if (servername == NULL) {
3820                 *printername_p = talloc_strdup(mem_ctx, printername);
3821                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3822                 return WERR_OK;
3823         }
3824
3825         if (servername[0] == '\\' && servername[1] == '\\') {
3826                 servername += 2;
3827         }
3828
3829         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3830         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3831
3832         return WERR_OK;
3833 }
3834
3835 /********************************************************************
3836  ********************************************************************/
3837
3838 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3839                                           const char *printername)
3840 {
3841         if (dm == NULL) {
3842                 return;
3843         }
3844
3845         dm->devicename = talloc_strndup(dm, printername,
3846                                         MIN(strlen(printername), 31));
3847 }
3848
3849 /********************************************************************
3850  * construct_printer_info_0
3851  * fill a printer_info_0 struct
3852  ********************************************************************/
3853
3854 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3855                                       const struct auth_session_info *session_info,
3856                                       struct messaging_context *msg_ctx,
3857                                       struct spoolss_PrinterInfo2 *info2,
3858                                       const char *servername,
3859                                       struct spoolss_PrinterInfo0 *r,
3860                                       int snum)
3861 {
3862         int count;
3863         struct printer_session_counter *session_counter;
3864         struct timeval setuptime;
3865         print_status_struct status;
3866         WERROR result;
3867
3868         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3869         if (!W_ERROR_IS_OK(result)) {
3870                 return result;
3871         }
3872
3873         if (servername) {
3874                 r->servername = talloc_strdup(mem_ctx, servername);
3875                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3876         } else {
3877                 r->servername = NULL;
3878         }
3879
3880         count = print_queue_length(msg_ctx, snum, &status);
3881
3882         /* check if we already have a counter for this printer */
3883         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3884                 if (session_counter->snum == snum)
3885                         break;
3886         }
3887
3888         /* it's the first time, add it to the list */
3889         if (session_counter == NULL) {
3890                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3891                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3892                 session_counter->snum           = snum;
3893                 session_counter->counter        = 0;
3894                 DLIST_ADD(counter_list, session_counter);
3895         }
3896
3897         /* increment it */
3898         session_counter->counter++;
3899
3900         r->cjobs                        = count;
3901         r->total_jobs                   = 0;
3902         r->total_bytes                  = 0;
3903
3904         get_startup_time(&setuptime);
3905         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3906
3907         /* JFM:
3908          * the global_counter should be stored in a TDB as it's common to all the clients
3909          * and should be zeroed on samba startup
3910          */
3911         r->global_counter               = session_counter->counter;
3912         r->total_pages                  = 0;
3913         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3914         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3915         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3916         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3917         r->spooling                     = 0;
3918         r->max_spooling                 = 0;
3919         r->session_counter              = session_counter->counter;
3920         r->num_error_out_of_paper       = 0x0;
3921         r->num_error_not_ready          = 0x0;          /* number of print failure */
3922         r->job_error                    = 0x0;
3923         r->number_of_processors         = 0x1;
3924         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3925         r->high_part_total_bytes        = 0x0;
3926
3927         /* ChangeID in milliseconds*/
3928         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3929                                     info2->sharename, &r->change_id);
3930
3931         r->last_error                   = WERR_OK;
3932         r->status                       = nt_printq_status(status.status);
3933         r->enumerate_network_printers   = 0x0;
3934         r->c_setprinter                 = 0x0;
3935         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3936         r->processor_level              = 0x6;          /* 6  ???*/
3937         r->ref_ic                       = 0;
3938         r->reserved2                    = 0;
3939         r->reserved3                    = 0;
3940
3941         return WERR_OK;
3942 }
3943
3944
3945 /********************************************************************
3946  * construct_printer_info1
3947  * fill a spoolss_PrinterInfo1 struct
3948 ********************************************************************/
3949
3950 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3951                                       const struct spoolss_PrinterInfo2 *info2,
3952                                       uint32_t flags,
3953                                       const char *servername,
3954                                       struct spoolss_PrinterInfo1 *r,
3955                                       int snum)
3956 {
3957         WERROR result;
3958
3959         r->flags                = flags;
3960
3961         if (info2->comment == NULL || info2->comment[0] == '\0') {
3962                 r->comment      = lp_comment(mem_ctx, snum);
3963         } else {
3964                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3965         }
3966         W_ERROR_HAVE_NO_MEMORY(r->comment);
3967
3968         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3969         if (!W_ERROR_IS_OK(result)) {
3970                 return result;
3971         }
3972
3973         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3974                                                   r->name,
3975                                                   info2->drivername,
3976                                                   r->comment);
3977         W_ERROR_HAVE_NO_MEMORY(r->description);
3978
3979         return WERR_OK;
3980 }
3981
3982 /********************************************************************
3983  * construct_printer_info2
3984  * fill a spoolss_PrinterInfo2 struct
3985 ********************************************************************/
3986
3987 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3988                                       struct messaging_context *msg_ctx,
3989                                       const struct spoolss_PrinterInfo2 *info2,
3990                                       const char *servername,
3991                                       struct spoolss_PrinterInfo2 *r,
3992                                       int snum)
3993 {
3994         int count;
3995         print_status_struct status;
3996         WERROR result;
3997
3998         count = print_queue_length(msg_ctx, snum, &status);
3999
4000         if (servername) {
4001                 r->servername           = talloc_strdup(mem_ctx, servername);
4002                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4003         } else {
4004                 r->servername           = NULL;
4005         }
4006
4007         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4008         if (!W_ERROR_IS_OK(result)) {
4009                 return result;
4010         }
4011
4012         r->sharename            = lp_servicename(mem_ctx, snum);
4013         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4014         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4015         W_ERROR_HAVE_NO_MEMORY(r->portname);
4016         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4017         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4018
4019         if (info2->comment[0] == '\0') {
4020                 r->comment      = lp_comment(mem_ctx, snum);
4021         } else {
4022                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4023         }
4024         W_ERROR_HAVE_NO_MEMORY(r->comment);
4025
4026         r->location     = talloc_strdup(mem_ctx, info2->location);
4027         if (info2->location[0] == '\0') {
4028                 const char *loc = NULL;
4029                 NTSTATUS nt_status;
4030
4031                 nt_status = printer_list_get_printer(mem_ctx,
4032                                                      info2->sharename,
4033                                                      NULL,
4034                                                      &loc,
4035                                                      NULL);
4036                 if (NT_STATUS_IS_OK(nt_status)) {
4037                         if (loc != NULL) {
4038                                 r->location = talloc_strdup(mem_ctx, loc);
4039                         }
4040                 }
4041         }
4042         W_ERROR_HAVE_NO_MEMORY(r->location);
4043
4044         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4045         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4046         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4047         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4048         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4049         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4050         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4051         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4052
4053         r->attributes           = info2->attributes;
4054
4055         r->priority             = info2->priority;
4056         r->defaultpriority      = info2->defaultpriority;
4057         r->starttime            = info2->starttime;
4058         r->untiltime            = info2->untiltime;
4059         r->status               = nt_printq_status(status.status);
4060         r->cjobs                = count;
4061         r->averageppm           = info2->averageppm;
4062
4063         if (info2->devmode != NULL) {
4064                 result = copy_devicemode(mem_ctx,
4065                                          info2->devmode,
4066                                          &r->devmode);
4067                 if (!W_ERROR_IS_OK(result)) {
4068                         return result;
4069                 }
4070         } else if (lp_default_devmode(snum)) {
4071                 result = spoolss_create_default_devmode(mem_ctx,
4072                                                         info2->printername,
4073                                                         &r->devmode);
4074                 if (!W_ERROR_IS_OK(result)) {
4075                         return result;
4076                 }
4077         } else {
4078                 r->devmode = NULL;
4079                 DEBUG(8,("Returning NULL Devicemode!\n"));
4080         }
4081
4082         compose_devicemode_devicename(r->devmode, r->printername);
4083
4084         r->secdesc = NULL;
4085
4086         if (info2->secdesc != NULL) {
4087                 /* don't use talloc_steal() here unless you do a deep steal of all
4088                    the SEC_DESC members */
4089
4090                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4091                 if (r->secdesc == NULL) {
4092                         return WERR_NOT_ENOUGH_MEMORY;
4093                 }
4094         }
4095
4096         return WERR_OK;
4097 }
4098
4099 /********************************************************************
4100  * construct_printer_info3
4101  * fill a spoolss_PrinterInfo3 struct
4102  ********************************************************************/
4103
4104 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4105                                       const struct spoolss_PrinterInfo2 *info2,
4106                                       const char *servername,
4107                                       struct spoolss_PrinterInfo3 *r,
4108                                       int snum)
4109 {
4110         /* These are the components of the SD we are returning. */
4111
4112         if (info2->secdesc != NULL) {
4113                 /* don't use talloc_steal() here unless you do a deep steal of all
4114                    the SEC_DESC members */
4115
4116                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4117                 if (r->secdesc == NULL) {
4118                         return WERR_NOT_ENOUGH_MEMORY;
4119                 }
4120         }
4121
4122         return WERR_OK;
4123 }
4124
4125 /********************************************************************
4126  * construct_printer_info4
4127  * fill a spoolss_PrinterInfo4 struct
4128  ********************************************************************/
4129
4130 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4131                                       const struct spoolss_PrinterInfo2 *info2,
4132                                       const char *servername,
4133                                       struct spoolss_PrinterInfo4 *r,
4134                                       int snum)
4135 {
4136         WERROR result;
4137
4138         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4139         if (!W_ERROR_IS_OK(result)) {
4140                 return result;
4141         }
4142
4143         if (servername) {
4144                 r->servername   = talloc_strdup(mem_ctx, servername);
4145                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4146         } else {
4147                 r->servername = NULL;
4148         }
4149
4150         r->attributes   = info2->attributes;
4151
4152         return WERR_OK;
4153 }
4154
4155 /********************************************************************
4156  * construct_printer_info5
4157  * fill a spoolss_PrinterInfo5 struct
4158  ********************************************************************/
4159
4160 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4161                                       const struct spoolss_PrinterInfo2 *info2,
4162                                       const char *servername,
4163                                       struct spoolss_PrinterInfo5 *r,
4164                                       int snum)
4165 {
4166         WERROR result;
4167
4168         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4169         if (!W_ERROR_IS_OK(result)) {
4170                 return result;
4171         }
4172
4173         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4174         W_ERROR_HAVE_NO_MEMORY(r->portname);
4175
4176         r->attributes   = info2->attributes;
4177
4178         /* these two are not used by NT+ according to MSDN */
4179         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4180         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4181
4182         return WERR_OK;
4183 }
4184
4185 /********************************************************************
4186  * construct_printer_info_6
4187  * fill a spoolss_PrinterInfo6 struct
4188  ********************************************************************/
4189
4190 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4191                                       struct messaging_context *msg_ctx,
4192                                       const struct spoolss_PrinterInfo2 *info2,
4193                                       const char *servername,
4194                                       struct spoolss_PrinterInfo6 *r,
4195                                       int snum)
4196 {
4197         print_status_struct status;
4198
4199         print_queue_length(msg_ctx, snum, &status);
4200
4201         r->status = nt_printq_status(status.status);
4202
4203         return WERR_OK;
4204 }
4205
4206 /********************************************************************
4207  * construct_printer_info7
4208  * fill a spoolss_PrinterInfo7 struct
4209  ********************************************************************/
4210
4211 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4212                                       struct messaging_context *msg_ctx,
4213                                       const char *servername,
4214                                       struct spoolss_PrinterInfo7 *r,
4215                                       int snum)
4216 {
4217         const struct auth_session_info *session_info;
4218         char *printer;
4219         WERROR werr;
4220         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4221         if (tmp_ctx == NULL) {
4222                 return WERR_NOT_ENOUGH_MEMORY;
4223         }
4224
4225         session_info = get_session_info_system();
4226         SMB_ASSERT(session_info != NULL);
4227
4228         printer = lp_servicename(tmp_ctx, snum);
4229         if (printer == NULL) {
4230                 DEBUG(0, ("invalid printer snum %d\n", snum));
4231                 werr = WERR_INVALID_PARAMETER;
4232                 goto out_tmp_free;
4233         }
4234
4235         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4236                                  servername, printer, NULL)) {
4237                 struct GUID guid;
4238                 struct GUID_txt_buf guid_txt;
4239                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4240                                            printer, &guid);
4241                 if (!W_ERROR_IS_OK(werr)) {
4242                         /*
4243                          * If we do not have a GUID entry in the registry, then
4244                          * try to retrieve it from AD and store it now.
4245                          */
4246                         werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4247                                                         &guid);
4248                         if (!W_ERROR_IS_OK(werr)) {
4249                                 DEBUG(1, ("Failed to retrieve GUID for "
4250                                           "printer [%s] from AD - "
4251                                           "Is the the printer still "
4252                                           "published ?\n", printer));
4253                                 goto out_tmp_free;
4254                         }
4255
4256                         werr = nt_printer_guid_store(msg_ctx, printer, guid);
4257                         if (!W_ERROR_IS_OK(werr)) {
4258                                 DEBUG(3, ("failed to store printer %s guid\n",
4259                                           printer));
4260                         }
4261                 }
4262                 r->guid = talloc_strdup_upper(mem_ctx,
4263                                              GUID_buf_string(&guid, &guid_txt));
4264                 r->action = DSPRINT_PUBLISH;
4265         } else {
4266                 r->guid = talloc_strdup(mem_ctx, "");
4267                 r->action = DSPRINT_UNPUBLISH;
4268         }
4269         if (r->guid == NULL) {
4270                 werr = WERR_NOT_ENOUGH_MEMORY;
4271                 goto out_tmp_free;
4272         }
4273
4274         werr = WERR_OK;
4275 out_tmp_free:
4276         talloc_free(tmp_ctx);
4277         return werr;
4278 }
4279
4280 /********************************************************************
4281  * construct_printer_info8
4282  * fill a spoolss_PrinterInfo8 struct
4283  ********************************************************************/
4284
4285 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4286                                       const struct spoolss_PrinterInfo2 *info2,
4287                                       const char *servername,
4288                                       struct spoolss_DeviceModeInfo *r,
4289                                       int snum)
4290 {
4291         WERROR result;
4292         const char *printername;
4293
4294         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4295         if (!W_ERROR_IS_OK(result)) {
4296                 return result;
4297         }
4298
4299         if (info2->devmode != NULL) {
4300                 result = copy_devicemode(mem_ctx,
4301                                          info2->devmode,
4302                                          &r->devmode);
4303                 if (!W_ERROR_IS_OK(result)) {
4304                         return result;
4305                 }
4306         } else if (lp_default_devmode(snum)) {
4307                 result = spoolss_create_default_devmode(mem_ctx,
4308                                                         info2->printername,
4309                                                         &r->devmode);
4310                 if (!W_ERROR_IS_OK(result)) {
4311                         return result;
4312                 }
4313         } else {
4314                 r->devmode = NULL;
4315                 DEBUG(8,("Returning NULL Devicemode!\n"));
4316         }
4317
4318         compose_devicemode_devicename(r->devmode, printername);
4319
4320         return WERR_OK;
4321 }
4322
4323 /********************************************************************
4324  Spoolss_enumprinters.
4325 ********************************************************************/
4326
4327 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4328                                            const struct auth_session_info *session_info,
4329                                            struct messaging_context *msg_ctx,
4330                                            const char *servername,
4331                                            uint32_t level,
4332                                            uint32_t flags,
4333                                            union spoolss_PrinterInfo **info_p,
4334                                            uint32_t *count_p)
4335 {
4336         int snum;
4337         int n_services;
4338         union spoolss_PrinterInfo *info = NULL;
4339         uint32_t count = 0;
4340         WERROR result = WERR_OK;
4341         struct dcerpc_binding_handle *b = NULL;
4342         TALLOC_CTX *tmp_ctx = NULL;
4343
4344         tmp_ctx = talloc_new(mem_ctx);
4345         if (!tmp_ctx) {
4346                 return WERR_NOT_ENOUGH_MEMORY;
4347         }
4348
4349         /*
4350          * printer shares are updated on client enumeration. The background
4351          * printer process updates printer_list.tdb at regular intervals.
4352          */
4353         become_root();
4354         delete_and_reload_printers(server_event_context(), msg_ctx);
4355         unbecome_root();
4356
4357         n_services = lp_numservices();
4358         *count_p = 0;
4359         *info_p = NULL;
4360
4361         for (snum = 0; snum < n_services; snum++) {
4362
4363                 const char *printer;
4364                 struct spoolss_PrinterInfo2 *info2;
4365
4366                 if (!snum_is_shared_printer(snum)) {
4367                         continue;
4368                 }
4369
4370                 printer = lp_const_servicename(snum);
4371
4372                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4373                         printer, snum));
4374
4375                 if (b == NULL) {
4376                         result = winreg_printer_binding_handle(tmp_ctx,
4377                                                                session_info,
4378                                                                msg_ctx,
4379                                                                &b);
4380                         if (!W_ERROR_IS_OK(result)) {
4381                                 goto out;
4382                         }
4383                 }
4384
4385                 result = winreg_create_printer(tmp_ctx, b,
4386                                                printer);
4387                 if (!W_ERROR_IS_OK(result)) {
4388                         goto out;
4389                 }
4390
4391                 info = talloc_realloc(tmp_ctx, info,
4392                                             union spoolss_PrinterInfo,
4393                                             count + 1);
4394                 if (!info) {
4395                         result = WERR_NOT_ENOUGH_MEMORY;
4396                         goto out;
4397                 }
4398
4399                 result = winreg_get_printer(tmp_ctx, b,
4400                                             printer, &info2);
4401                 if (!W_ERROR_IS_OK(result)) {
4402                         goto out;
4403                 }
4404
4405                 switch (level) {
4406                 case 0:
4407                         result = construct_printer_info0(info, session_info,
4408                                                          msg_ctx, info2,
4409                                                          servername,
4410                                                          &info[count].info0, snum);
4411                         break;
4412                 case 1:
4413                         result = construct_printer_info1(info, info2, flags,
4414                                                          servername,
4415                                                          &info[count].info1, snum);
4416                         break;
4417                 case 2:
4418                         result = construct_printer_info2(info, msg_ctx, info2,
4419                                                          servername,
4420                                                          &info[count].info2, snum);
4421                         break;
4422                 case 4:
4423                         result = construct_printer_info4(info, info2,
4424                                                          servername,
4425                                                          &info[count].info4, snum);
4426                         break;
4427                 case 5:
4428                         result = construct_printer_info5(info, info2,
4429                                                          servername,
4430                                                          &info[count].info5, snum);
4431                         break;
4432
4433                 default:
4434                         result = WERR_INVALID_LEVEL;
4435                         goto out;
4436                 }
4437
4438                 if (!W_ERROR_IS_OK(result)) {
4439                         goto out;
4440                 }
4441
4442                 count++;
4443         }
4444
4445 out:
4446         if (W_ERROR_IS_OK(result)) {
4447                 *info_p = talloc_move(mem_ctx, &info);
4448                 *count_p = count;
4449         }
4450
4451         talloc_free(tmp_ctx);
4452
4453         return result;
4454 }
4455
4456 /********************************************************************
4457  * handle enumeration of printers at level 0
4458  ********************************************************************/
4459
4460 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4461                                   const struct auth_session_info *session_info,
4462                                   struct messaging_context *msg_ctx,
4463                                   uint32_t flags,
4464                                   const char *servername,
4465                                   union spoolss_PrinterInfo **info,
4466                                   uint32_t *count)
4467 {
4468         DEBUG(4,("enum_all_printers_info_0\n"));
4469
4470         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4471                                             servername, 0, flags, info, count);
4472 }
4473
4474
4475 /********************************************************************
4476 ********************************************************************/
4477
4478 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4479                                        const struct auth_session_info *session_info,
4480                                        struct messaging_context *msg_ctx,
4481                                        const char *servername,
4482                                        uint32_t flags,
4483                                        union spoolss_PrinterInfo **info,
4484                                        uint32_t *count)
4485 {
4486         DEBUG(4,("enum_all_printers_info_1\n"));
4487
4488         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4489                                             servername, 1, flags, info, count);
4490 }
4491
4492 /********************************************************************
4493  enum_all_printers_info_1_local.
4494 *********************************************************************/
4495
4496 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4497                                              const struct auth_session_info *session_info,
4498                                              struct messaging_context *msg_ctx,
4499                                              const char *servername,
4500                                              union spoolss_PrinterInfo **info,
4501                                              uint32_t *count)
4502 {
4503         DEBUG(4,("enum_all_printers_info_1_local\n"));
4504
4505         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4506                                         servername, PRINTER_ENUM_ICON8, info, count);
4507 }
4508
4509 /********************************************************************
4510  enum_all_printers_info_1_name.
4511 *********************************************************************/
4512
4513 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4514                                             const struct auth_session_info *session_info,
4515                                             struct messaging_context *msg_ctx,
4516                                             const char *servername,
4517                                             union spoolss_PrinterInfo **info,
4518                                             uint32_t *count)
4519 {
4520         const char *s = servername;
4521
4522         DEBUG(4,("enum_all_printers_info_1_name\n"));
4523
4524         if (servername != NULL &&
4525             (servername[0] == '\\') && (servername[1] == '\\')) {
4526                 s = servername + 2;
4527         }
4528
4529         if (!is_myname_or_ipaddr(s)) {
4530                 return WERR_INVALID_NAME;
4531         }
4532
4533         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4534                                         servername, PRINTER_ENUM_ICON8, info, count);
4535 }
4536
4537 /********************************************************************
4538  enum_all_printers_info_1_network.
4539 *********************************************************************/
4540
4541 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4542                                                const struct auth_session_info *session_info,
4543                                                struct messaging_context *msg_ctx,
4544                                                const char *servername,
4545                                                union spoolss_PrinterInfo **info,
4546                                                uint32_t *count)
4547 {
4548         const char *s = servername;
4549
4550         DEBUG(4,("enum_all_printers_info_1_network\n"));
4551
4552         /* If we respond to a enum_printers level 1 on our name with flags
4553            set to PRINTER_ENUM_REMOTE with a list of printers then these
4554            printers incorrectly appear in the APW browse list.
4555            Specifically the printers for the server appear at the workgroup
4556            level where all the other servers in the domain are
4557            listed. Windows responds to this call with a
4558            WERR_CAN_NOT_COMPLETE so we should do the same. */
4559
4560         if (servername != NULL &&
4561             (servername[0] == '\\') && (servername[1] == '\\')) {
4562                  s = servername + 2;
4563         }
4564
4565         if (is_myname_or_ipaddr(s)) {
4566                  return WERR_CAN_NOT_COMPLETE;
4567         }
4568
4569         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4570                                         servername, PRINTER_ENUM_NAME, info, count);
4571 }
4572
4573 /********************************************************************
4574  * api_spoolss_enumprinters
4575  *
4576  * called from api_spoolss_enumprinters (see this to understand)
4577  ********************************************************************/
4578
4579 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4580                                        const struct auth_session_info *session_info,
4581                                        struct messaging_context *msg_ctx,
4582                                        const char *servername,
4583                                        union spoolss_PrinterInfo **info,
4584                                        uint32_t *count)
4585 {
4586         DEBUG(4,("enum_all_printers_info_2\n"));
4587
4588         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4589                                             servername, 2, 0, info, count);
4590 }
4591
4592 /********************************************************************
4593  * handle enumeration of printers at level 1
4594  ********************************************************************/
4595
4596 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4597                                   const struct auth_session_info *session_info,
4598                                   struct messaging_context *msg_ctx,
4599                                   uint32_t flags,
4600                                   const char *servername,
4601                                   union spoolss_PrinterInfo **info,
4602                                   uint32_t *count)
4603 {
4604         /* Not all the flags are equals */
4605
4606         if (flags & PRINTER_ENUM_LOCAL) {
4607                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4608                                                       msg_ctx, servername, info, count);
4609         }
4610
4611         if (flags & PRINTER_ENUM_NAME) {
4612                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4613                                                      msg_ctx, servername, info,
4614                                                      count);
4615         }
4616
4617         if (flags & PRINTER_ENUM_NETWORK) {
4618                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4619                                                         msg_ctx, servername, info,
4620                                                         count);
4621         }
4622
4623         return WERR_OK; /* NT4sp5 does that */
4624 }
4625
4626 /********************************************************************
4627  * handle enumeration of printers at level 2
4628  ********************************************************************/
4629
4630 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4631                                   const struct auth_session_info *session_info,
4632                                   struct messaging_context *msg_ctx,
4633                                   uint32_t flags,
4634                                   const char *servername,
4635                                   union spoolss_PrinterInfo **info,
4636                                   uint32_t *count)
4637 {
4638         if (flags & PRINTER_ENUM_LOCAL) {
4639
4640                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4641                                                 servername,
4642                                                 info, count);
4643         }
4644
4645         if (flags & PRINTER_ENUM_NAME) {
4646                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4647                         return WERR_INVALID_NAME;
4648                 }
4649
4650                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4651                                                 servername,
4652                                                 info, count);
4653         }
4654
4655         if (flags & PRINTER_ENUM_REMOTE) {
4656                 return WERR_INVALID_LEVEL;
4657         }
4658
4659         return WERR_OK;
4660 }
4661
4662 /********************************************************************
4663  * handle enumeration of printers at level 4
4664  ********************************************************************/
4665
4666 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4667                                   const struct auth_session_info *session_info,
4668                                   struct messaging_context *msg_ctx,
4669                                   uint32_t flags,
4670                                   const char *servername,
4671                                   union spoolss_PrinterInfo **info,
4672                                   uint32_t *count)
4673 {
4674         DEBUG(4,("enum_all_printers_info_4\n"));
4675
4676         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4677                                             servername, 4, flags, info, count);
4678 }
4679
4680
4681 /********************************************************************
4682  * handle enumeration of printers at level 5
4683  ********************************************************************/
4684
4685 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4686                                   const struct auth_session_info *session_info,
4687                                   struct messaging_context *msg_ctx,
4688                                   uint32_t flags,
4689                                   const char *servername,
4690                                   union spoolss_PrinterInfo **info,
4691                                   uint32_t *count)
4692 {
4693         DEBUG(4,("enum_all_printers_info_5\n"));
4694
4695         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4696                                             servername, 5, flags, info, count);
4697 }
4698
4699 /****************************************************************
4700  _spoolss_EnumPrinters
4701 ****************************************************************/
4702
4703 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4704                              struct spoolss_EnumPrinters *r)
4705 {
4706         const struct auth_session_info *session_info = get_session_info_system();
4707         WERROR result;
4708
4709         /* that's an [in out] buffer */
4710
4711         if (!r->in.buffer && (r->in.offered != 0)) {
4712                 return WERR_INVALID_PARAMETER;
4713         }
4714
4715         DEBUG(4,("_spoolss_EnumPrinters\n"));
4716
4717         *r->out.needed = 0;
4718         *r->out.count = 0;
4719         *r->out.info = NULL;
4720
4721         /*
4722          * Level 1:
4723          *          flags==PRINTER_ENUM_NAME
4724          *           if name=="" then enumerates all printers
4725          *           if name!="" then enumerate the printer
4726          *          flags==PRINTER_ENUM_REMOTE
4727          *          name is NULL, enumerate printers
4728          * Level 2: name!="" enumerates printers, name can't be NULL
4729          * Level 3: doesn't exist
4730          * Level 4: does a local registry lookup
4731          * Level 5: same as Level 2
4732          */
4733
4734         if (r->in.server && r->in.server[0] == '\0') {
4735                 r->in.server = NULL;
4736         }
4737
4738         switch (r->in.level) {
4739         case 0:
4740                 result = enumprinters_level0(p->mem_ctx, session_info,
4741                                              p->msg_ctx, r->in.flags,
4742                                              r->in.server,
4743                                              r->out.info, r->out.count);
4744                 break;
4745         case 1:
4746                 result = enumprinters_level1(p->mem_ctx, session_info,
4747                                              p->msg_ctx, r->in.flags,
4748                                              r->in.server,
4749                                              r->out.info, r->out.count);
4750                 break;
4751         case 2:
4752                 result = enumprinters_level2(p->mem_ctx, session_info,
4753                                              p->msg_ctx, r->in.flags,
4754                                              r->in.server,
4755                                              r->out.info, r->out.count);
4756                 break;
4757         case 4:
4758                 result = enumprinters_level4(p->mem_ctx, session_info,
4759                                              p->msg_ctx, r->in.flags,
4760                                              r->in.server,
4761                                              r->out.info, r->out.count);
4762                 break;
4763         case 5:
4764                 result = enumprinters_level5(p->mem_ctx, session_info,
4765                                              p->msg_ctx, r->in.flags,
4766                                              r->in.server,
4767                                              r->out.info, r->out.count);
4768                 break;
4769         default:
4770                 return WERR_INVALID_LEVEL;
4771         }
4772
4773         if (!W_ERROR_IS_OK(result)) {
4774                 return result;
4775         }
4776
4777         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4778                                                      spoolss_EnumPrinters,
4779                                                      *r->out.info, r->in.level,
4780                                                      *r->out.count);
4781         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4782         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4783
4784         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4785 }
4786
4787 /****************************************************************
4788  _spoolss_GetPrinter
4789 ****************************************************************/
4790
4791 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4792                            struct spoolss_GetPrinter *r)
4793 {
4794         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4795         struct spoolss_PrinterInfo2 *info2 = NULL;
4796         WERROR result = WERR_OK;
4797         int snum;
4798
4799         /* that's an [in out] buffer */
4800
4801         if (!r->in.buffer && (r->in.offered != 0)) {
4802                 result = WERR_INVALID_PARAMETER;
4803                 goto err_info_free;
4804         }
4805
4806         *r->out.needed = 0;
4807
4808         if (Printer == NULL) {
4809                 result = WERR_INVALID_HANDLE;
4810                 goto err_info_free;
4811         }
4812
4813         if (Printer->printer_type == SPLHND_SERVER) {
4814
4815                 struct dcerpc_binding_handle *b;
4816
4817                 if (r->in.level != 3) {
4818                         result = WERR_INVALID_LEVEL;
4819                         goto err_info_free;
4820                 }
4821
4822                 result = winreg_printer_binding_handle(p->mem_ctx,
4823                                                        get_session_info_system(),
4824                                                        p->msg_ctx,
4825                                                        &b);
4826                 if (!W_ERROR_IS_OK(result)) {
4827                         goto err_info_free;
4828                 }
4829
4830                 result = winreg_get_printserver_secdesc(p->mem_ctx,
4831                                                         b,
4832                                                         &r->out.info->info3.secdesc);
4833                 if (!W_ERROR_IS_OK(result)) {
4834                         goto err_info_free;
4835                 }
4836
4837                 goto done;
4838         }
4839
4840         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4841                 result = WERR_INVALID_HANDLE;
4842                 goto err_info_free;
4843         }
4844
4845         result = winreg_get_printer_internal(p->mem_ctx,
4846                                     get_session_info_system(),
4847                                     p->msg_ctx,
4848                                     lp_const_servicename(snum),
4849                                     &info2);
4850         if (!W_ERROR_IS_OK(result)) {
4851                 goto err_info_free;
4852         }
4853
4854         switch (r->in.level) {
4855         case 0:
4856                 result = construct_printer_info0(p->mem_ctx,
4857                                                  get_session_info_system(),
4858                                                  p->msg_ctx,
4859                                                  info2,
4860                                                  Printer->servername,
4861                                                  &r->out.info->info0,
4862                                                  snum);
4863                 break;
4864         case 1:
4865                 result = construct_printer_info1(p->mem_ctx, info2,
4866                                                  PRINTER_ENUM_ICON8,
4867                                                  Printer->servername,
4868                                                  &r->out.info->info1, snum);
4869                 break;
4870         case 2:
4871                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4872                                                  Printer->servername,
4873                                                  &r->out.info->info2, snum);
4874                 break;
4875         case 3:
4876                 result = construct_printer_info3(p->mem_ctx, info2,
4877                                                  Printer->servername,
4878                                                  &r->out.info->info3, snum);
4879                 break;
4880         case 4:
4881                 result = construct_printer_info4(p->mem_ctx, info2,
4882                                                  Printer->servername,
4883                                                  &r->out.info->info4, snum);
4884                 break;
4885         case 5:
4886                 result = construct_printer_info5(p->mem_ctx, info2,
4887                                                  Printer->servername,
4888                                                  &r->out.info->info5, snum);
4889                 break;
4890         case 6:
4891                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4892                                                  Printer->servername,
4893                                                  &r->out.info->info6, snum);
4894                 break;
4895         case 7:
4896                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4897                                                  Printer->servername,
4898                                                  &r->out.info->info7, snum);
4899                 break;
4900         case 8:
4901                 result = construct_printer_info8(p->mem_ctx, info2,
4902                                                  Printer->servername,
4903                                                  &r->out.info->info8, snum);
4904                 break;
4905         default:
4906                 result = WERR_INVALID_LEVEL;
4907                 break;
4908         }
4909         TALLOC_FREE(info2);
4910
4911         if (!W_ERROR_IS_OK(result)) {
4912                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4913                           r->in.level, win_errstr(result)));
4914                 goto err_info_free;
4915         }
4916  done:
4917         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4918                                                r->out.info, r->in.level);
4919         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4920
4921         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4922
4923 err_info_free:
4924         TALLOC_FREE(r->out.info);
4925         return result;
4926 }
4927
4928 /********************************************************************
4929  ********************************************************************/
4930
4931 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4932         do { \
4933                 if (in && strlen(in)) { \
4934                         out = talloc_strdup(mem_ctx, in); \
4935                 } else { \
4936                         out = talloc_strdup(mem_ctx, ""); \
4937                 } \
4938                 W_ERROR_HAVE_NO_MEMORY(out); \
4939         } while (0);
4940
4941 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4942         do { \
4943                 if (in && strlen(in)) { \
4944                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4945                 } else { \
4946                         out = talloc_strdup(mem_ctx, ""); \
4947                 } \
4948                 W_ERROR_HAVE_NO_MEMORY(out); \
4949         } while (0);
4950
4951 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4952                                                   const char **string_array,
4953                                                   const char ***presult,
4954                                                   const char *cservername,
4955                                                   const char *arch,
4956                                                   int version)
4957 {
4958         int i;
4959         size_t num_strings = 0;
4960         const char **array = NULL;
4961
4962         if (string_array == NULL) {
4963                 return WERR_INVALID_PARAMETER;
4964         }
4965
4966         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4967                 const char *str = NULL;
4968
4969                 if (cservername == NULL || arch == NULL) {
4970                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4971                 } else {
4972                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4973                 }
4974
4975                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4976                         TALLOC_FREE(array);
4977                         return WERR_NOT_ENOUGH_MEMORY;
4978                 }
4979         }
4980
4981         if (i > 0) {
4982                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4983                              &array, &num_strings);
4984         }
4985
4986         if (presult != NULL) {
4987                 *presult = array;
4988         } else {
4989                 talloc_free(array);
4990         }
4991
4992         return WERR_OK;
4993 }
4994
4995 /********************************************************************
4996  * fill a spoolss_DriverInfo1 struct
4997  ********************************************************************/
4998
4999 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
5000                                         struct spoolss_DriverInfo1 *r,
5001                                         const struct spoolss_DriverInfo8 *driver,
5002                                         const char *servername)
5003 {
5004         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5005         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5006
5007         return WERR_OK;
5008 }
5009
5010 /********************************************************************
5011  * fill a spoolss_DriverInfo2 struct
5012  ********************************************************************/
5013
5014 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5015                                         struct spoolss_DriverInfo2 *r,
5016                                         const struct spoolss_DriverInfo8 *driver,
5017                                         const char *servername)
5018
5019 {
5020         const char *cservername = canon_servername(servername);
5021
5022         r->version              = driver->version;
5023
5024         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5025         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5026         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5027         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5028
5029         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5030                                driver->architecture,
5031                                driver->version,
5032                                driver->driver_path,
5033                                r->driver_path);
5034
5035         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5036                                driver->architecture,
5037                                driver->version,
5038                                driver->data_file,
5039                                r->data_file);
5040
5041         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5042                                driver->architecture,
5043                                driver->version,
5044                                driver->config_file,
5045                                r->config_file);
5046
5047         return WERR_OK;
5048 }
5049
5050 /********************************************************************
5051  * fill a spoolss_DriverInfo3 struct
5052  ********************************************************************/
5053
5054 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5055                                         struct spoolss_DriverInfo3 *r,
5056                                         const struct spoolss_DriverInfo8 *driver,
5057                                         const char *servername)
5058 {
5059         const char *cservername = canon_servername(servername);
5060
5061         r->version              = driver->version;
5062
5063         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5064         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5065         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5066         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5067
5068         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5069                                driver->architecture,
5070                                driver->version,
5071                                driver->driver_path,
5072                                r->driver_path);
5073
5074         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5075                                driver->architecture,
5076                                driver->version,
5077                                driver->data_file,
5078                                r->data_file);
5079
5080         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5081                                driver->architecture,
5082                                driver->version,
5083                                driver->config_file,
5084                                r->config_file);
5085
5086         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5087                                driver->architecture,
5088                                driver->version,
5089                                driver->help_file,
5090                                r->help_file);
5091
5092         FILL_DRIVER_STRING(mem_ctx,
5093                            driver->monitor_name,
5094                            r->monitor_name);
5095
5096         FILL_DRIVER_STRING(mem_ctx,
5097                            driver->default_datatype,
5098                            r->default_datatype);
5099
5100         return string_array_from_driver_info(mem_ctx,
5101                                              driver->dependent_files,
5102                                              &r->dependent_files,
5103                                              cservername,
5104                                              driver->architecture,
5105                                              driver->version);
5106 }
5107
5108 /********************************************************************
5109  * fill a spoolss_DriverInfo4 struct
5110  ********************************************************************/
5111
5112 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5113                                         struct spoolss_DriverInfo4 *r,
5114                                         const struct spoolss_DriverInfo8 *driver,
5115                                         const char *servername)
5116 {
5117         const char *cservername = canon_servername(servername);
5118         WERROR result;
5119
5120         r->version              = driver->version;
5121
5122         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5123         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5124         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5125         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5126
5127         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5128                                driver->architecture,
5129                                driver->version,
5130                                driver->driver_path,
5131                                r->driver_path);
5132
5133         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5134                                driver->architecture,
5135                                driver->version,
5136                                driver->data_file,
5137                                r->data_file);
5138
5139         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5140                                driver->architecture,
5141                                driver->version,
5142                                driver->config_file,
5143                                r->config_file);
5144
5145         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5146                                driver->architecture,
5147                                driver->version,
5148                                driver->help_file,
5149                                r->help_file);
5150
5151         result = string_array_from_driver_info(mem_ctx,
5152                                                driver->dependent_files,
5153                                                &r->dependent_files,
5154                                                cservername,
5155                                                driver->architecture,
5156                                                driver->version);
5157         if (!W_ERROR_IS_OK(result)) {
5158                 return result;
5159         }
5160
5161         FILL_DRIVER_STRING(mem_ctx,
5162                            driver->monitor_name,
5163                            r->monitor_name);
5164
5165         FILL_DRIVER_STRING(mem_ctx,
5166                            driver->default_datatype,
5167                            r->default_datatype);
5168
5169
5170         result = string_array_from_driver_info(mem_ctx,
5171                                                driver->previous_names,
5172                                                &r->previous_names,
5173                                                NULL, NULL, 0);
5174
5175         return result;
5176 }
5177
5178 /********************************************************************
5179  * fill a spoolss_DriverInfo5 struct
5180  ********************************************************************/
5181
5182 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5183                                         struct spoolss_DriverInfo5 *r,
5184                                         const struct spoolss_DriverInfo8 *driver,
5185                                         const char *servername)
5186 {
5187         const char *cservername = canon_servername(servername);
5188
5189         r->version              = driver->version;
5190
5191         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5192         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5193         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5194         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5195
5196         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5197                                driver->architecture,
5198                                driver->version,
5199                                driver->driver_path,
5200                                r->driver_path);
5201
5202         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5203                                driver->architecture,
5204                                driver->version,
5205                                driver->data_file,
5206                                r->data_file);
5207
5208         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5209                                driver->architecture,
5210                                driver->version,
5211                                driver->config_file,
5212                                r->config_file);
5213
5214         r->driver_attributes    = 0;
5215         r->config_version       = 0;
5216         r->driver_version       = 0;
5217
5218         return WERR_OK;
5219 }
5220 /********************************************************************
5221  * fill a spoolss_DriverInfo6 struct
5222  ********************************************************************/
5223
5224 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5225                                         struct spoolss_DriverInfo6 *r,
5226                                         const struct spoolss_DriverInfo8 *driver,
5227                                         const char *servername)
5228 {
5229         const char *cservername = canon_servername(servername);
5230         WERROR result;
5231
5232         r->version              = driver->version;
5233
5234         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5235         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5236         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5237         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5238
5239         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5240                                driver->architecture,
5241                                driver->version,
5242                                driver->driver_path,
5243                                r->driver_path);
5244
5245         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5246                                driver->architecture,
5247                                driver->version,
5248                                driver->data_file,
5249                                r->data_file);
5250
5251         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5252                                driver->architecture,
5253                                driver->version,
5254                                driver->config_file,
5255                                r->config_file);
5256
5257         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5258                                driver->architecture,
5259                                driver->version,
5260                                driver->help_file,
5261                                r->help_file);
5262
5263         FILL_DRIVER_STRING(mem_ctx,
5264                            driver->monitor_name,
5265                            r->monitor_name);
5266
5267         FILL_DRIVER_STRING(mem_ctx,
5268                            driver->default_datatype,
5269                            r->default_datatype);
5270
5271         result = string_array_from_driver_info(mem_ctx,
5272                                                driver->dependent_files,
5273                                                &r->dependent_files,
5274                                                cservername,
5275                                                driver->architecture,
5276                                                driver->version);
5277         if (!W_ERROR_IS_OK(result)) {
5278                 return result;
5279         }
5280
5281         result = string_array_from_driver_info(mem_ctx,
5282                                                driver->previous_names,
5283                                                &r->previous_names,
5284                                                NULL, NULL, 0);
5285         if (!W_ERROR_IS_OK(result)) {
5286                 return result;
5287         }
5288
5289         r->driver_date          = driver->driver_date;
5290         r->driver_version       = driver->driver_version;
5291
5292         FILL_DRIVER_STRING(mem_ctx,
5293                            driver->manufacturer_name,
5294                            r->manufacturer_name);
5295         FILL_DRIVER_STRING(mem_ctx,
5296                            driver->manufacturer_url,
5297                            r->manufacturer_url);
5298         FILL_DRIVER_STRING(mem_ctx,
5299                            driver->hardware_id,
5300                            r->hardware_id);
5301         FILL_DRIVER_STRING(mem_ctx,
5302                            driver->provider,
5303                            r->provider);
5304
5305         return WERR_OK;
5306 }
5307
5308 /********************************************************************
5309  * fill a spoolss_DriverInfo8 struct
5310  ********************************************************************/
5311
5312 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5313                                         struct spoolss_DriverInfo8 *r,
5314                                         const struct spoolss_DriverInfo8 *driver,
5315                                         const char *servername)
5316 {
5317         const char *cservername = canon_servername(servername);
5318         WERROR result;
5319
5320         r->version              = driver->version;
5321
5322         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5323         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5324         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5325         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5326
5327         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5328                                driver->architecture,
5329                                driver->version,
5330                                driver->driver_path,
5331                                r->driver_path);
5332
5333         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5334                                driver->architecture,
5335                                driver->version,
5336                                driver->data_file,
5337                                r->data_file);
5338
5339         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5340                                driver->architecture,
5341                                driver->version,
5342                                driver->config_file,
5343                                r->config_file);
5344
5345         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5346                                driver->architecture,
5347                                driver->version,
5348                                driver->help_file,
5349                                r->help_file);
5350
5351         FILL_DRIVER_STRING(mem_ctx,
5352                            driver->monitor_name,
5353                            r->monitor_name);
5354
5355         FILL_DRIVER_STRING(mem_ctx,
5356                            driver->default_datatype,
5357                            r->default_datatype);
5358
5359         result = string_array_from_driver_info(mem_ctx,
5360                                                driver->dependent_files,
5361                                                &r->dependent_files,
5362                                                cservername,
5363                                                driver->architecture,
5364                                                driver->version);
5365         if (!W_ERROR_IS_OK(result)) {
5366                 return result;
5367         }
5368
5369         result = string_array_from_driver_info(mem_ctx,
5370                                                driver->previous_names,
5371                                                &r->previous_names,
5372                                                NULL, NULL, 0);
5373         if (!W_ERROR_IS_OK(result)) {
5374                 return result;
5375         }
5376
5377         r->driver_date          = driver->driver_date;
5378         r->driver_version       = driver->driver_version;
5379
5380         FILL_DRIVER_STRING(mem_ctx,
5381                            driver->manufacturer_name,
5382                            r->manufacturer_name);
5383         FILL_DRIVER_STRING(mem_ctx,
5384                            driver->manufacturer_url,
5385                            r->manufacturer_url);
5386         FILL_DRIVER_STRING(mem_ctx,
5387                            driver->hardware_id,
5388                            r->hardware_id);
5389         FILL_DRIVER_STRING(mem_ctx,
5390                            driver->provider,
5391                            r->provider);
5392
5393         FILL_DRIVER_STRING(mem_ctx,
5394                            driver->print_processor,
5395                            r->print_processor);
5396         FILL_DRIVER_STRING(mem_ctx,
5397                            driver->vendor_setup,
5398                            r->vendor_setup);
5399
5400         result = string_array_from_driver_info(mem_ctx,
5401                                                driver->color_profiles,
5402                                                &r->color_profiles,
5403                                                NULL, NULL, 0);
5404         if (!W_ERROR_IS_OK(result)) {
5405                 return result;
5406         }
5407
5408         FILL_DRIVER_STRING(mem_ctx,
5409                            driver->inf_path,
5410                            r->inf_path);
5411
5412         r->printer_driver_attributes    = driver->printer_driver_attributes;
5413
5414         result = string_array_from_driver_info(mem_ctx,
5415                                                driver->core_driver_dependencies,
5416                                                &r->core_driver_dependencies,
5417                                                NULL, NULL, 0);
5418         if (!W_ERROR_IS_OK(result)) {
5419                 return result;
5420         }
5421
5422         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5423         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5424
5425         return WERR_OK;
5426 }
5427
5428 #if 0 /* disabled until marshalling issues are resolved - gd */
5429 /********************************************************************
5430  ********************************************************************/
5431
5432 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5433                                           struct spoolss_DriverFileInfo *r,
5434                                           const char *cservername,
5435                                           const char *file_name,
5436                                           enum spoolss_DriverFileType file_type,
5437                                           uint32_t file_version)
5438 {
5439         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5440                                           cservername, file_name);
5441         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5442         r->file_type    = file_type;
5443         r->file_version = file_version;
5444
5445         return WERR_OK;
5446 }
5447
5448 /********************************************************************
5449  ********************************************************************/
5450
5451 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5452                                                  const struct spoolss_DriverInfo8 *driver,
5453                                                  const char *cservername,
5454                                                  struct spoolss_DriverFileInfo **info_p,
5455                                                  uint32_t *count_p)
5456 {
5457         struct spoolss_DriverFileInfo *info = NULL;
5458         uint32_t count = 0;
5459         WERROR result;
5460         uint32_t i;
5461
5462         *info_p = NULL;
5463         *count_p = 0;
5464
5465         if (strlen(driver->driver_path)) {
5466                 info = talloc_realloc(mem_ctx, info,
5467                                             struct spoolss_DriverFileInfo,
5468                                             count + 1);
5469                 W_ERROR_HAVE_NO_MEMORY(info);
5470                 result = fill_spoolss_DriverFileInfo(info,
5471                                                      &info[count],
5472                                                      cservername,
5473                                                      driver->driver_path,
5474                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5475                                                      0);
5476                 W_ERROR_NOT_OK_RETURN(result);
5477                 count++;
5478         }
5479
5480         if (strlen(driver->config_file)) {
5481                 info = talloc_realloc(mem_ctx, info,
5482                                             struct spoolss_DriverFileInfo,
5483                                             count + 1);
5484                 W_ERROR_HAVE_NO_MEMORY(info);
5485                 result = fill_spoolss_DriverFileInfo(info,
5486                                                      &info[count],
5487                                                      cservername,
5488                                                      driver->config_file,
5489                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5490                                                      0);
5491                 W_ERROR_NOT_OK_RETURN(result);
5492                 count++;
5493         }
5494
5495         if (strlen(driver->data_file)) {
5496                 info = talloc_realloc(mem_ctx, info,
5497                                             struct spoolss_DriverFileInfo,
5498                                             count + 1);
5499                 W_ERROR_HAVE_NO_MEMORY(info);
5500                 result = fill_spoolss_DriverFileInfo(info,
5501                                                      &info[count],
5502                                                      cservername,
5503                                                      driver->data_file,
5504                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5505                                                      0);
5506                 W_ERROR_NOT_OK_RETURN(result);
5507                 count++;
5508         }
5509
5510         if (strlen(driver->help_file)) {
5511                 info = talloc_realloc(mem_ctx, info,
5512                                             struct spoolss_DriverFileInfo,
5513                                             count + 1);
5514                 W_ERROR_HAVE_NO_MEMORY(info);
5515                 result = fill_spoolss_DriverFileInfo(info,
5516                                                      &info[count],
5517                                                      cservername,
5518                                                      driver->help_file,
5519                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5520                                                      0);
5521                 W_ERROR_NOT_OK_RETURN(result);
5522                 count++;
5523         }
5524
5525         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5526                 info = talloc_realloc(mem_ctx, info,
5527                                             struct spoolss_DriverFileInfo,
5528                                             count + 1);
5529                 W_ERROR_HAVE_NO_MEMORY(info);
5530                 result = fill_spoolss_DriverFileInfo(info,
5531                                                      &info[count],
5532                                                      cservername,
5533                                                      driver->dependent_files[i],
5534                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5535                                                      0);
5536                 W_ERROR_NOT_OK_RETURN(result);
5537                 count++;
5538         }
5539
5540         *info_p = info;
5541         *count_p = count;
5542
5543         return WERR_OK;
5544 }
5545
5546 /********************************************************************
5547  * fill a spoolss_DriverInfo101 struct
5548  ********************************************************************/
5549
5550 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5551                                           struct spoolss_DriverInfo101 *r,
5552                                           const struct spoolss_DriverInfo8 *driver,
5553                                           const char *servername)
5554 {
5555         const char *cservername = canon_servername(servername);
5556         WERROR result;
5557
5558         r->version              = driver->version;
5559
5560         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5561         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5562         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5563         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5564
5565         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5566                                                     cservername,
5567                                                     &r->file_info,
5568                                                     &r->file_count);
5569         if (!W_ERROR_IS_OK(result)) {
5570                 return result;
5571         }
5572
5573         FILL_DRIVER_STRING(mem_ctx,
5574                            driver->monitor_name,
5575                            r->monitor_name);
5576
5577         FILL_DRIVER_STRING(mem_ctx,
5578                            driver->default_datatype,
5579                            r->default_datatype);
5580
5581         result = string_array_from_driver_info(mem_ctx,
5582                                                driver->previous_names,
5583                                                &r->previous_names,
5584                                                NULL, NULL, 0);
5585         if (!W_ERROR_IS_OK(result)) {
5586                 return result;
5587         }
5588
5589         r->driver_date          = driver->driver_date;
5590         r->driver_version       = driver->driver_version;
5591
5592         FILL_DRIVER_STRING(mem_ctx,
5593                            driver->manufacturer_name,
5594                            r->manufacturer_name);
5595         FILL_DRIVER_STRING(mem_ctx,
5596                            driver->manufacturer_url,
5597                            r->manufacturer_url);
5598         FILL_DRIVER_STRING(mem_ctx,
5599                            driver->hardware_id,
5600                            r->hardware_id);
5601         FILL_DRIVER_STRING(mem_ctx,
5602                            driver->provider,
5603                            r->provider);
5604
5605         return WERR_OK;
5606 }
5607 #endif
5608 /********************************************************************
5609  ********************************************************************/
5610
5611 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5612                                                   const struct auth_session_info *session_info,
5613                                                   struct messaging_context *msg_ctx,
5614                                                   uint32_t level,
5615                                                   union spoolss_DriverInfo *r,
5616                                                   int snum,
5617                                                   const char *servername,
5618                                                   const char *architecture,
5619                                                   uint32_t version)
5620 {
5621         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5622         struct spoolss_DriverInfo8 *driver;
5623         WERROR result;
5624         struct dcerpc_binding_handle *b;
5625         TALLOC_CTX *tmp_ctx = NULL;
5626
5627         if (level == 101) {
5628                 return WERR_INVALID_LEVEL;
5629         }
5630
5631         tmp_ctx = talloc_new(mem_ctx);
5632         if (!tmp_ctx) {
5633                 return WERR_NOT_ENOUGH_MEMORY;
5634         }
5635
5636         result = winreg_printer_binding_handle(tmp_ctx,
5637                                                session_info,
5638                                                msg_ctx,
5639                                                &b);
5640         if (!W_ERROR_IS_OK(result)) {
5641                 goto done;
5642         }
5643
5644         result = winreg_get_printer(tmp_ctx, b,
5645                                     lp_const_servicename(snum),
5646                                     &pinfo2);
5647
5648         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5649                 win_errstr(result)));
5650
5651         if (!W_ERROR_IS_OK(result)) {
5652                 result = WERR_INVALID_PRINTER_NAME;
5653                 goto done;
5654         }
5655
5656         result = winreg_get_driver(tmp_ctx, b,
5657                                    architecture,
5658                                    pinfo2->drivername, version, &driver);
5659
5660         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5661                 win_errstr(result)));
5662
5663         if (!W_ERROR_IS_OK(result)) {
5664                 /*
5665                  * Is this a W2k client ?
5666                  */
5667
5668                 if (version < 3) {
5669                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5670                         goto done;
5671                 }
5672
5673                 /* Yes - try again with a WinNT driver. */
5674                 version = 2;
5675                 result = winreg_get_driver(tmp_ctx, b,
5676                                            architecture,
5677                                            pinfo2->drivername,
5678                                            version, &driver);
5679                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5680                         win_errstr(result)));
5681                 if (!W_ERROR_IS_OK(result)) {
5682                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5683                         goto done;
5684                 }
5685         }
5686
5687         /* these are allocated on mem_ctx and not tmp_ctx because they are
5688          * the 'return value' and need to utlive this call */
5689         switch (level) {
5690         case 1:
5691                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5692                 break;
5693         case 2:
5694                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5695                 break;
5696         case 3:
5697                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5698                 break;
5699         case 4:
5700                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5701                 break;
5702         case 5:
5703                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5704                 break;
5705         case 6:
5706                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5707                 break;
5708         case 8:
5709                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5710                 break;
5711 #if 0 /* disabled until marshalling issues are resolved - gd */
5712         case 101:
5713                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5714                 break;
5715 #endif
5716         default:
5717                 result = WERR_INVALID_LEVEL;
5718                 break;
5719         }
5720
5721 done:
5722         talloc_free(tmp_ctx);
5723         return result;
5724 }
5725
5726 /****************************************************************
5727  _spoolss_GetPrinterDriver2
5728 ****************************************************************/
5729
5730 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5731                                   struct spoolss_GetPrinterDriver2 *r)
5732 {
5733         struct printer_handle *printer;
5734         WERROR result;
5735         uint32_t version = r->in.client_major_version;
5736
5737         int snum;
5738
5739         /* that's an [in out] buffer */
5740
5741         if (!r->in.buffer && (r->in.offered != 0)) {
5742                 result = WERR_INVALID_PARAMETER;
5743                 goto err_info_free;
5744         }
5745
5746         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5747
5748         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5749                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5750                 result = WERR_INVALID_PRINTER_NAME;
5751                 goto err_info_free;
5752         }
5753
5754         *r->out.needed = 0;
5755         *r->out.server_major_version = 0;
5756         *r->out.server_minor_version = 0;
5757
5758         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5759                 result = WERR_INVALID_HANDLE;
5760                 goto err_info_free;
5761         }
5762
5763         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5764                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5765                         "downgrading to v3\n"));
5766                 version = SPOOLSS_DRIVER_VERSION_200X;
5767         }
5768
5769         result = construct_printer_driver_info_level(p->mem_ctx,
5770                                                      get_session_info_system(),
5771                                                      p->msg_ctx,
5772                                                      r->in.level, r->out.info,
5773                                                      snum, printer->servername,
5774                                                      r->in.architecture,
5775                                                      version);
5776         if (!W_ERROR_IS_OK(result)) {
5777                 goto err_info_free;
5778         }
5779
5780         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5781                                                r->out.info, r->in.level);
5782         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5783
5784         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5785
5786 err_info_free:
5787         TALLOC_FREE(r->out.info);
5788         return result;
5789 }
5790
5791
5792 /****************************************************************
5793  _spoolss_StartPagePrinter
5794 ****************************************************************/
5795
5796 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5797                                  struct spoolss_StartPagePrinter *r)
5798 {
5799         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5800
5801         if (!Printer) {
5802                 DEBUG(3,("_spoolss_StartPagePrinter: "
5803                         "Error in startpageprinter printer handle\n"));
5804                 return WERR_INVALID_HANDLE;
5805         }
5806
5807         Printer->page_started = true;
5808         return WERR_OK;
5809 }
5810
5811 /****************************************************************
5812  _spoolss_EndPagePrinter
5813 ****************************************************************/
5814
5815 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5816                                struct spoolss_EndPagePrinter *r)
5817 {
5818         int snum;
5819
5820         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5821
5822         if (!Printer) {
5823                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5824                         OUR_HANDLE(r->in.handle)));
5825                 return WERR_INVALID_HANDLE;
5826         }
5827
5828         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5829                 return WERR_INVALID_HANDLE;
5830
5831         Printer->page_started = false;
5832         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5833
5834         return WERR_OK;
5835 }
5836
5837 /****************************************************************
5838  _spoolss_StartDocPrinter
5839 ****************************************************************/
5840
5841 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5842                                 struct spoolss_StartDocPrinter *r)
5843 {
5844         struct spoolss_DocumentInfo1 *info_1;
5845         int snum;
5846         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5847         WERROR werr;
5848         char *rhost;
5849         int rc;
5850
5851         if (!Printer) {
5852                 DEBUG(2,("_spoolss_StartDocPrinter: "
5853                         "Invalid handle (%s:%u:%u)\n",
5854                         OUR_HANDLE(r->in.handle)));
5855                 return WERR_INVALID_HANDLE;
5856         }
5857
5858         if (Printer->jobid) {
5859                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5860                           "StartDocPrinter called twice! "
5861                           "(existing jobid = %d)\n", Printer->jobid));
5862                 return WERR_INVALID_HANDLE;
5863         }
5864
5865         if (r->in.info_ctr->level != 1) {
5866                 return WERR_INVALID_LEVEL;
5867         }
5868
5869         info_1 = r->in.info_ctr->info.info1;
5870
5871         /*
5872          * a nice thing with NT is it doesn't listen to what you tell it.
5873          * when asked to send _only_ RAW datas, it tries to send datas
5874          * in EMF format.
5875          *
5876          * So I add checks like in NT Server ...
5877          */
5878
5879         if (info_1->datatype) {
5880                 /*
5881                  * The v4 driver model used in Windows 8 declares print jobs
5882                  * intended to bypass the XPS processing layer by setting
5883                  * datatype to "XPS_PASS" instead of "RAW".
5884                  */
5885                 if ((strcmp(info_1->datatype, "RAW") != 0)
5886                  && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5887                         *r->out.job_id = 0;
5888                         return WERR_INVALID_DATATYPE;
5889                 }
5890         }
5891
5892         /* get the share number of the printer */
5893         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5894                 return WERR_INVALID_HANDLE;
5895         }
5896
5897         rc = get_remote_hostname(p->remote_address,
5898                                  &rhost,
5899                                  p->mem_ctx);
5900         if (rc < 0) {
5901                 return WERR_NOT_ENOUGH_MEMORY;
5902         }
5903         if (strequal(rhost,"UNKNOWN")) {
5904                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5905                                                          p->mem_ctx);
5906                 if (rhost == NULL) {
5907                         return WERR_NOT_ENOUGH_MEMORY;
5908                 }
5909         }
5910
5911         werr = print_job_start(p->session_info,
5912                                p->msg_ctx,
5913                                rhost,
5914                                snum,
5915                                info_1->document_name,
5916                                info_1->output_file,
5917                                Printer->devmode,
5918                                &Printer->jobid);
5919
5920         /* An error occured in print_job_start() so return an appropriate
5921            NT error code. */
5922
5923         if (!W_ERROR_IS_OK(werr)) {
5924                 return werr;
5925         }
5926
5927         Printer->document_started = true;
5928         *r->out.job_id = Printer->jobid;
5929
5930         return WERR_OK;
5931 }
5932
5933 /****************************************************************
5934  _spoolss_EndDocPrinter
5935 ****************************************************************/
5936
5937 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5938                               struct spoolss_EndDocPrinter *r)
5939 {
5940         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5941         NTSTATUS status;
5942         int snum;
5943
5944         if (!Printer) {
5945                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5946                         OUR_HANDLE(r->in.handle)));
5947                 return WERR_INVALID_HANDLE;
5948         }
5949
5950         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5951                 return WERR_INVALID_HANDLE;
5952         }
5953
5954         Printer->document_started = false;
5955         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5956         if (!NT_STATUS_IS_OK(status)) {
5957                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5958                           "print_job_end failed [%s]\n",
5959                           nt_errstr(status)));
5960         }
5961
5962         Printer->jobid = 0;
5963         return ntstatus_to_werror(status);
5964 }
5965
5966 /****************************************************************
5967  _spoolss_WritePrinter
5968 ****************************************************************/
5969
5970 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5971                              struct spoolss_WritePrinter *r)
5972 {
5973         ssize_t buffer_written;
5974         int snum;
5975         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5976
5977         if (!Printer) {
5978                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5979                         OUR_HANDLE(r->in.handle)));
5980                 *r->out.num_written = r->in._data_size;
5981                 return WERR_INVALID_HANDLE;
5982         }
5983
5984         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5985                 return WERR_INVALID_HANDLE;
5986
5987         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5988         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5989                                                    snum, Printer->jobid,
5990                                                    (const char *)r->in.data.data,
5991                                                    (size_t)r->in._data_size);
5992         if (buffer_written == (ssize_t)-1) {
5993                 *r->out.num_written = 0;
5994                 if (errno == ENOSPC)
5995                         return WERR_NO_SPOOL_SPACE;
5996                 else
5997                         return WERR_ACCESS_DENIED;
5998         }
5999
6000         *r->out.num_written = r->in._data_size;
6001
6002         return WERR_OK;
6003 }
6004
6005 /********************************************************************
6006  * api_spoolss_getprinter
6007  * called from the spoolss dispatcher
6008  *
6009  ********************************************************************/
6010
6011 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
6012                               struct pipes_struct *p)
6013 {
6014         const struct auth_session_info *session_info = p->session_info;
6015         int snum;
6016         WERROR errcode = WERR_INVALID_FUNCTION;
6017         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6018
6019         if (!Printer) {
6020                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
6021                         OUR_HANDLE(handle)));
6022                 return WERR_INVALID_HANDLE;
6023         }
6024
6025         if (!get_printer_snum(p, handle, &snum, NULL))
6026                 return WERR_INVALID_HANDLE;
6027
6028         switch (command) {
6029         case SPOOLSS_PRINTER_CONTROL_PAUSE:
6030                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
6031                 break;
6032         case SPOOLSS_PRINTER_CONTROL_RESUME:
6033         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6034                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6035                 break;
6036         case SPOOLSS_PRINTER_CONTROL_PURGE:
6037                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6038                 break;
6039         default:
6040                 return WERR_INVALID_LEVEL;
6041         }
6042
6043         return errcode;
6044 }
6045
6046
6047 /****************************************************************
6048  _spoolss_AbortPrinter
6049  * From MSDN: "Deletes printer's spool file if printer is configured
6050  * for spooling"
6051 ****************************************************************/
6052
6053 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6054                              struct spoolss_AbortPrinter *r)
6055 {
6056         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
6057         int             snum;
6058         WERROR          errcode = WERR_OK;
6059
6060         if (!Printer) {
6061                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6062                         OUR_HANDLE(r->in.handle)));
6063                 return WERR_INVALID_HANDLE;
6064         }
6065
6066         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6067                 return WERR_INVALID_HANDLE;
6068
6069         if (!Printer->document_started) {
6070                 return WERR_SPL_NO_STARTDOC;
6071         }
6072
6073         errcode = print_job_delete(p->session_info,
6074                                    p->msg_ctx,
6075                                    snum,
6076                                    Printer->jobid);
6077
6078         return errcode;
6079 }
6080
6081 /********************************************************************
6082  * called by spoolss_api_setprinter
6083  * when updating a printer description
6084  ********************************************************************/
6085
6086 static WERROR update_printer_sec(struct policy_handle *handle,
6087                                  struct pipes_struct *p,
6088                                  struct sec_desc_buf *secdesc_ctr)
6089 {
6090         struct spoolss_security_descriptor *new_secdesc = NULL;
6091         struct spoolss_security_descriptor *old_secdesc = NULL;
6092         const char *printer = NULL;
6093         WERROR result;
6094         int snum = -1;
6095         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6096         struct dcerpc_binding_handle *b;
6097         TALLOC_CTX *tmp_ctx = NULL;
6098         bool ok = false;
6099
6100         if (!Printer) {
6101                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6102                          OUR_HANDLE(handle)));
6103
6104                 result = WERR_INVALID_HANDLE;
6105                 goto done;
6106         }
6107
6108         if (secdesc_ctr == NULL) {
6109                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6110                 result = WERR_INVALID_PARAMETER;
6111                 goto done;
6112         }
6113
6114         switch (Printer->printer_type) {
6115         case SPLHND_SERVER:
6116                 break;
6117         case SPLHND_PRINTER:
6118                 if (!get_printer_snum(p, handle, &snum, NULL)) {
6119                         DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6120                                  OUR_HANDLE(handle)));
6121                         result = WERR_INVALID_HANDLE;
6122                         goto done;
6123                 }
6124                 printer = lp_const_servicename(snum);
6125                 break;
6126         default:
6127                 break;
6128         }
6129
6130         /* Check the user has permissions to change the security
6131            descriptor.  By experimentation with two NT machines, the user
6132            requires Full Access to the printer to change security
6133            information. */
6134
6135         switch (Printer->printer_type) {
6136         case SPLHND_SERVER:
6137                 ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
6138                 break;
6139         case SPLHND_PRINTER:
6140                 ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
6141                 break;
6142         default:
6143                 break;
6144         }
6145
6146         if (!ok) {
6147                 DEBUG(4,("update_printer_sec: updated denied by printer permissions "
6148                         "(access_granted: 0x%08x)\n", Printer->access_granted));
6149                 result = WERR_ACCESS_DENIED;
6150                 goto done;
6151         }
6152
6153         tmp_ctx = talloc_new(p->mem_ctx);
6154         if (!tmp_ctx) {
6155                 return WERR_NOT_ENOUGH_MEMORY;
6156         }
6157
6158         result = winreg_printer_binding_handle(tmp_ctx,
6159                                                get_session_info_system(),
6160                                                p->msg_ctx,
6161                                                &b);
6162         if (!W_ERROR_IS_OK(result)) {
6163                 goto done;
6164         }
6165
6166         /* NT seems to like setting the security descriptor even though
6167            nothing may have actually changed. */
6168
6169         if (printer != NULL) {
6170                 result = winreg_get_printer_secdesc(tmp_ctx, b,
6171                                                     printer,
6172                                                     &old_secdesc);
6173         } else {
6174                 result = winreg_get_printserver_secdesc(tmp_ctx, b,
6175                                                         &old_secdesc);
6176         }
6177         if (!W_ERROR_IS_OK(result)) {
6178                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6179                 result = WERR_INVALID_HANDLE;
6180                 goto done;
6181         }
6182
6183         if (DEBUGLEVEL >= 10) {
6184                 struct security_acl *the_acl;
6185                 int i;
6186
6187                 the_acl = old_secdesc->dacl;
6188                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6189                            printer, the_acl->num_aces));
6190
6191                 for (i = 0; i < the_acl->num_aces; i++) {
6192                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6193                                            &the_acl->aces[i].trustee),
6194                                   the_acl->aces[i].access_mask));
6195                 }
6196
6197                 the_acl = secdesc_ctr->sd->dacl;
6198
6199                 if (the_acl) {
6200                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6201                                    printer, the_acl->num_aces));
6202
6203                         for (i = 0; i < the_acl->num_aces; i++) {
6204                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6205                                                    &the_acl->aces[i].trustee),
6206                                            the_acl->aces[i].access_mask));
6207                         }
6208                 } else {
6209                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6210                 }
6211         }
6212
6213         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6214         if (new_secdesc == NULL) {
6215                 result = WERR_NOT_ENOUGH_MEMORY;
6216                 goto done;
6217         }
6218
6219         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6220                 result = WERR_OK;
6221                 goto done;
6222         }
6223
6224         if (printer != NULL) {
6225                 result = winreg_set_printer_secdesc(tmp_ctx, b,
6226                                                     printer,
6227                                                     new_secdesc);
6228         } else {
6229                 result = winreg_set_printserver_secdesc(tmp_ctx, b,
6230                                                         new_secdesc);
6231         }
6232
6233 done:
6234         talloc_free(tmp_ctx);
6235         return result;
6236 }
6237
6238 /********************************************************************
6239  Canonicalize printer info from a client
6240  ********************************************************************/
6241
6242 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6243                              struct spoolss_SetPrinterInfo2 *info2,
6244                              int snum)
6245 {
6246         fstring printername;
6247         const char *p;
6248
6249         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6250                 "portname=%s drivername=%s comment=%s location=%s\n",
6251                 info2->servername, info2->printername, info2->sharename,
6252                 info2->portname, info2->drivername, info2->comment,
6253                 info2->location));
6254
6255         /* we force some elements to "correct" values */
6256         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6257         if (info2->servername == NULL) {
6258                 return false;
6259         }
6260         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6261         if (info2->sharename == NULL) {
6262                 return false;
6263         }
6264
6265         /* check to see if we allow printername != sharename */
6266         if (lp_force_printername(snum)) {
6267                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6268                                         lp_netbios_name(), info2->sharename);
6269         } else {
6270                 /* make sure printername is in \\server\printername format */
6271                 fstrcpy(printername, info2->printername);
6272                 p = printername;
6273                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6274                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6275                                 p++;
6276                 }
6277
6278                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6279                                         lp_netbios_name(), p);
6280         }
6281         if (info2->printername == NULL) {
6282                 return false;
6283         }
6284
6285         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6286         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6287
6288         return true;
6289 }
6290
6291 /****************************************************************************
6292 ****************************************************************************/
6293
6294 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6295 {
6296         char *cmd = lp_addport_command(talloc_tos());
6297         char *command = NULL;
6298         int ret;
6299         bool is_print_op = false;
6300
6301         if ( !*cmd ) {
6302                 return WERR_ACCESS_DENIED;
6303         }
6304
6305         command = talloc_asprintf(ctx,
6306                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6307         if (!command) {
6308                 return WERR_NOT_ENOUGH_MEMORY;
6309         }
6310
6311         if ( token )
6312                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6313
6314         DEBUG(10,("Running [%s]\n", command));
6315
6316         /********* BEGIN SePrintOperatorPrivilege **********/
6317
6318         if ( is_print_op )
6319                 become_root();
6320
6321         ret = smbrun(command, NULL, NULL);
6322
6323         if ( is_print_op )
6324                 unbecome_root();
6325
6326         /********* END SePrintOperatorPrivilege **********/
6327
6328         DEBUGADD(10,("returned [%d]\n", ret));
6329
6330         TALLOC_FREE(command);
6331
6332         if ( ret != 0 ) {
6333                 return WERR_ACCESS_DENIED;
6334         }
6335
6336         return WERR_OK;
6337 }
6338
6339 /****************************************************************************
6340 ****************************************************************************/
6341
6342 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6343                                    int snum)
6344 {
6345         /*
6346          * As we do not know if we are embedded in the file server process
6347          * or not, we have to pretend that all shares are in use.
6348          */
6349         return true;
6350 }
6351
6352 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6353                              struct spoolss_SetPrinterInfo2 *info2,
6354                              const char *remote_machine,
6355                              struct messaging_context *msg_ctx)
6356 {
6357         char *cmd = lp_addprinter_command(talloc_tos());
6358         char **qlines;
6359         char *command = NULL;
6360         int numlines;
6361         int ret;
6362         int fd;
6363         bool is_print_op = false;
6364
6365         if (!remote_machine) {
6366                 return false;
6367         }
6368
6369         command = talloc_asprintf(ctx,
6370                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6371                         cmd, info2->printername, info2->sharename,
6372                         info2->portname, info2->drivername,
6373                         info2->location, info2->comment, remote_machine);
6374         if (!command) {
6375                 return false;
6376         }
6377
6378         if ( token )
6379                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6380
6381         DEBUG(10,("Running [%s]\n", command));
6382
6383         /********* BEGIN SePrintOperatorPrivilege **********/
6384
6385         if ( is_print_op )
6386                 become_root();
6387
6388         ret = smbrun(command, &fd, NULL);
6389         if (ret == 0) {
6390                 /* Tell everyone we updated smb.conf. */
6391                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6392         }
6393
6394         if ( is_print_op )
6395                 unbecome_root();
6396
6397         /********* END SePrintOperatorPrivilege **********/
6398
6399         DEBUGADD(10,("returned [%d]\n", ret));
6400
6401         TALLOC_FREE(command);
6402
6403         if ( ret != 0 ) {
6404                 if (fd != -1)
6405                         close(fd);
6406                 return false;
6407         }
6408
6409         /* reload our services immediately */
6410         become_root();
6411         reload_services(NULL, spoolss_conn_snum_used, false);
6412         unbecome_root();
6413
6414         numlines = 0;
6415         /* Get lines and convert them back to dos-codepage */
6416         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6417         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6418         close(fd);
6419
6420         /* Set the portname to what the script says the portname should be. */
6421         /* but don't require anything to be return from the script exit a good error code */
6422
6423         if (numlines) {
6424                 /* Set the portname to what the script says the portname should be. */
6425                 info2->portname = talloc_strdup(ctx, qlines[0]);
6426                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6427         }
6428
6429         TALLOC_FREE(qlines);
6430         return true;
6431 }
6432
6433 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6434                                const struct auth_session_info *session_info,
6435                                struct messaging_context *msg_ctx,
6436                                int snum,
6437                                struct spoolss_SetPrinterInfo2 *printer,
6438                                struct spoolss_PrinterInfo2 *old_printer)
6439 {
6440         bool force_update = (old_printer == NULL);
6441         const char *dnsdomname;
6442         const char *longname;
6443         const char *uncname;
6444         const char *spooling;
6445         DATA_BLOB buffer;
6446         WERROR result = WERR_OK;
6447         struct dcerpc_binding_handle *b;
6448         TALLOC_CTX *tmp_ctx;
6449         bool ok;
6450
6451         tmp_ctx = talloc_new(mem_ctx);
6452         if (!tmp_ctx) {
6453                 return WERR_NOT_ENOUGH_MEMORY;
6454         }
6455
6456         result = winreg_printer_binding_handle(tmp_ctx,
6457                                                session_info,
6458                                                msg_ctx,
6459                                                &b);
6460         if (!W_ERROR_IS_OK(result)) {
6461                 goto done;
6462         }
6463
6464         if (printer->drivername != NULL &&
6465             (force_update ||
6466              !strequal(printer->drivername, old_printer->drivername))) {
6467                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6468                 if (!ok) {
6469                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6470                         result = WERR_INVALID_DATA;
6471                         goto done;
6472                 }
6473                 result = winreg_set_printer_dataex(tmp_ctx, b,
6474                                           printer->sharename,
6475                                           SPOOL_DSSPOOLER_KEY,
6476                                           SPOOL_REG_DRIVERNAME,
6477                                           REG_SZ,
6478                                           buffer.data,
6479                                           buffer.length);
6480                 if (!W_ERROR_IS_OK(result)) {
6481                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6482                         goto done;
6483                 }
6484
6485                 if (!force_update) {
6486                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6487                                 printer->drivername));
6488
6489                         notify_printer_driver(server_event_context(), msg_ctx,
6490                                               snum, printer->drivername ?
6491                                               printer->drivername : "");
6492                 }
6493         }
6494
6495         if (printer->comment != NULL &&
6496             (force_update ||
6497              !strequal(printer->comment, old_printer->comment))) {
6498                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6499                 if (!ok) {
6500                         DEBUG(0, ("comment data corrupted\n"));
6501                         result = WERR_INVALID_DATA;
6502                         goto done;
6503                 }
6504                 result = winreg_set_printer_dataex(tmp_ctx, b,
6505                                           printer->sharename,
6506                                           SPOOL_DSSPOOLER_KEY,
6507                                           SPOOL_REG_DESCRIPTION,
6508                                           REG_SZ,
6509                                           buffer.data,
6510                                           buffer.length);
6511                 if (!W_ERROR_IS_OK(result)) {
6512                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6513                         goto done;
6514                 }
6515
6516                 if (!force_update) {
6517                         notify_printer_comment(server_event_context(), msg_ctx,
6518                                                snum, printer->comment ?
6519                                                printer->comment : "");
6520                 }
6521         }
6522
6523         if (printer->sharename != NULL &&
6524             (force_update ||
6525              !strequal(printer->sharename, old_printer->sharename))) {
6526                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6527                 if (!ok) {
6528                         DEBUG(0, ("sharename data corrupted\n"));
6529                         result = WERR_INVALID_DATA;
6530                         goto done;
6531                 }
6532                 result = winreg_set_printer_dataex(tmp_ctx, b,
6533                                           printer->sharename,
6534                                           SPOOL_DSSPOOLER_KEY,
6535                                           SPOOL_REG_PRINTSHARENAME,
6536                                           REG_SZ,
6537                                           buffer.data,
6538                                           buffer.length);
6539                 if (!W_ERROR_IS_OK(result)) {
6540                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6541                         goto done;
6542                 }
6543
6544                 if (!force_update) {
6545                         notify_printer_sharename(server_event_context(),
6546                                                  msg_ctx,
6547                                                  snum, printer->sharename ?
6548                                                  printer->sharename : "");
6549                 }
6550
6551                 /* name change, purge any cache entries for the old */
6552                 prune_printername_cache();
6553         }
6554
6555         if (printer->printername != NULL &&
6556             (force_update ||
6557              !strequal(printer->printername, old_printer->printername))) {
6558                 const char *p;
6559
6560                 p = strrchr(printer->printername, '\\' );
6561                 if (p != NULL) {
6562                         p++;
6563                 } else {
6564                         p = printer->printername;
6565                 }
6566
6567                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6568                 if (!ok) {
6569                         DEBUG(0, ("printername data corrupted\n"));
6570                         result = WERR_INVALID_DATA;
6571                         goto done;
6572                 }
6573                 result = winreg_set_printer_dataex(tmp_ctx, b,
6574                                           printer->sharename,
6575                                           SPOOL_DSSPOOLER_KEY,
6576                                           SPOOL_REG_PRINTERNAME,
6577                                           REG_SZ,
6578                                           buffer.data,
6579                                           buffer.length);
6580                 if (!W_ERROR_IS_OK(result)) {
6581                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6582                         goto done;
6583                 }
6584
6585                 if (!force_update) {
6586                         notify_printer_printername(server_event_context(),
6587                                                    msg_ctx, snum, p ? p : "");
6588                 }
6589
6590                 /* name change, purge any cache entries for the old */
6591                 prune_printername_cache();
6592         }
6593
6594         if (printer->portname != NULL &&
6595             (force_update ||
6596              !strequal(printer->portname, old_printer->portname))) {
6597                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6598                 if (!ok) {
6599                         DEBUG(0, ("portname data corrupted\n"));
6600                         result = WERR_INVALID_DATA;
6601                         goto done;
6602                 }
6603                 result = winreg_set_printer_dataex(tmp_ctx, b,
6604                                           printer->sharename,
6605                                           SPOOL_DSSPOOLER_KEY,
6606                                           SPOOL_REG_PORTNAME,
6607                                           REG_SZ,
6608                                           buffer.data,
6609                                           buffer.length);
6610                 if (!W_ERROR_IS_OK(result)) {
6611                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6612                         goto done;
6613                 }
6614
6615                 if (!force_update) {
6616                         notify_printer_port(server_event_context(),
6617                                             msg_ctx, snum, printer->portname ?
6618                                             printer->portname : "");
6619                 }
6620         }
6621
6622         if (printer->location != NULL &&
6623             (force_update ||
6624              !strequal(printer->location, old_printer->location))) {
6625                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6626                 if (!ok) {
6627                         DEBUG(0, ("location data corrupted\n"));
6628                         result = WERR_INVALID_DATA;
6629                         goto done;
6630                 }
6631                 result = winreg_set_printer_dataex(tmp_ctx, b,
6632                                           printer->sharename,
6633                                           SPOOL_DSSPOOLER_KEY,
6634                                           SPOOL_REG_LOCATION,
6635                                           REG_SZ,
6636                                           buffer.data,
6637                                           buffer.length);
6638                 if (!W_ERROR_IS_OK(result)) {
6639                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6640                         goto done;
6641                 }
6642
6643                 if (!force_update) {
6644                         notify_printer_location(server_event_context(),
6645                                                 msg_ctx, snum,
6646                                                 printer->location ?
6647                                                 printer->location : "");
6648                 }
6649         }
6650
6651         if (printer->sepfile != NULL &&
6652             (force_update ||
6653              !strequal(printer->sepfile, old_printer->sepfile))) {
6654                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6655                 if (!ok) {
6656                         DEBUG(0, ("sepfile data corrupted\n"));
6657                         result = WERR_INVALID_DATA;
6658                         goto done;
6659                 }
6660                 result = winreg_set_printer_dataex(tmp_ctx, b,
6661                                           printer->sharename,
6662                                           SPOOL_DSSPOOLER_KEY,
6663                                           SPOOL_REG_PRINTSEPARATORFILE,
6664                                           REG_SZ,
6665                                           buffer.data,
6666                                           buffer.length);
6667                 if (!W_ERROR_IS_OK(result)) {
6668                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6669                         goto done;
6670                 }
6671
6672                 if (!force_update) {
6673                         notify_printer_sepfile(server_event_context(),
6674                                                msg_ctx, snum,
6675                                                printer->sepfile ?
6676                                                printer->sepfile : "");
6677                 }
6678         }
6679
6680         if (printer->starttime != 0 &&
6681             (force_update ||
6682              printer->starttime != old_printer->starttime)) {
6683                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6684                 SIVAL(buffer.data, 0, printer->starttime);
6685                 result = winreg_set_printer_dataex(tmp_ctx, b,
6686                                           printer->sharename,
6687                                           SPOOL_DSSPOOLER_KEY,
6688                                           SPOOL_REG_PRINTSTARTTIME,
6689                                           REG_DWORD,
6690                                           buffer.data,
6691                                           buffer.length);
6692                 if (!W_ERROR_IS_OK(result)) {
6693                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6694                         goto done;
6695                 }
6696         }
6697
6698         if (printer->untiltime != 0 &&
6699             (force_update ||
6700              printer->untiltime != old_printer->untiltime)) {
6701                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6702                 SIVAL(buffer.data, 0, printer->untiltime);
6703                 result = winreg_set_printer_dataex(tmp_ctx, b,
6704                                           printer->sharename,
6705                                           SPOOL_DSSPOOLER_KEY,
6706                                           SPOOL_REG_PRINTENDTIME,
6707                                           REG_DWORD,
6708                                           buffer.data,
6709                                           buffer.length);
6710                 if (!W_ERROR_IS_OK(result)) {
6711                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6712                         goto done;
6713                 }
6714         }
6715
6716         if (force_update || printer->priority != old_printer->priority) {
6717                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6718                 SIVAL(buffer.data, 0, printer->priority);
6719                 result = winreg_set_printer_dataex(tmp_ctx, b,
6720                                           printer->sharename,
6721                                           SPOOL_DSSPOOLER_KEY,
6722                                           SPOOL_REG_PRIORITY,
6723                                           REG_DWORD,
6724                                           buffer.data,
6725                                           buffer.length);
6726                 if (!W_ERROR_IS_OK(result)) {
6727                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6728                         goto done;
6729                 }
6730         }
6731
6732         if (force_update || printer->attributes != old_printer->attributes) {
6733                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6734                 SIVAL(buffer.data, 0, (printer->attributes &
6735                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6736                 result = winreg_set_printer_dataex(tmp_ctx, b,
6737                                           printer->sharename,
6738                                           SPOOL_DSSPOOLER_KEY,
6739                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6740                                           REG_DWORD,
6741                                           buffer.data,
6742                                           buffer.length);
6743                 if (!W_ERROR_IS_OK(result)) {
6744                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6745                         goto done;
6746                 }
6747
6748                 switch (printer->attributes & 0x3) {
6749                         case 0:
6750                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6751                                 break;
6752                         case 1:
6753                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6754                                 break;
6755                         case 2:
6756                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6757                                 break;
6758                         default:
6759                                 spooling = "unknown";
6760                 }
6761                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6762                 if (!ok) {
6763                         DEBUG(0, ("printSpooling data corrupted\n"));
6764                         result = WERR_INVALID_DATA;
6765                         goto done;
6766                 }
6767                 winreg_set_printer_dataex(tmp_ctx, b,
6768                                           printer->sharename,
6769                                           SPOOL_DSSPOOLER_KEY,
6770                                           SPOOL_REG_PRINTSPOOLING,
6771                                           REG_SZ,
6772                                           buffer.data,
6773                                           buffer.length);
6774         }
6775
6776         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6777         if (!ok) {
6778                 DEBUG(0, ("shortServerName data corrupted\n"));
6779                 result = WERR_INVALID_DATA;
6780                 goto done;
6781         }
6782         result = winreg_set_printer_dataex(tmp_ctx, b,
6783                                   printer->sharename,
6784                                   SPOOL_DSSPOOLER_KEY,
6785                                   SPOOL_REG_SHORTSERVERNAME,
6786                                   REG_SZ,
6787                                   buffer.data,
6788                                   buffer.length);
6789         if (!W_ERROR_IS_OK(result)) {
6790                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6791                 goto done;
6792         }
6793
6794         dnsdomname = get_mydnsfullname();
6795         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6796                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6797         } else {
6798                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6799         }
6800         if (longname == NULL) {
6801                 result = WERR_NOT_ENOUGH_MEMORY;
6802                 goto done;
6803         }
6804
6805         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6806         if (!ok) {
6807                 DEBUG(0, ("longname data corrupted\n"));
6808                 result = WERR_INVALID_DATA;
6809                 goto done;
6810         }
6811         result = winreg_set_printer_dataex(tmp_ctx, b,
6812                                            printer->sharename,
6813                                            SPOOL_DSSPOOLER_KEY,
6814                                            SPOOL_REG_SERVERNAME,
6815                                            REG_SZ,
6816                                            buffer.data,
6817                                            buffer.length);
6818         if (!W_ERROR_IS_OK(result)) {
6819                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6820                 goto done;
6821         }
6822
6823         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6824                                   lp_netbios_name(), printer->sharename);
6825         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6826         if (!ok) {
6827                 DEBUG(0, ("uncName data corrupted\n"));
6828                 result = WERR_INVALID_DATA;
6829                 goto done;
6830         }
6831         result = winreg_set_printer_dataex(tmp_ctx, b,
6832                                   printer->sharename,
6833                                   SPOOL_DSSPOOLER_KEY,
6834                                   SPOOL_REG_UNCNAME,
6835                                   REG_SZ,
6836                                   buffer.data,
6837                                   buffer.length);
6838         if (!W_ERROR_IS_OK(result)) {
6839                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6840                 goto done;
6841         }
6842
6843 done:
6844         talloc_free(tmp_ctx);
6845         return result;
6846 }
6847
6848 /********************************************************************
6849  * Called by spoolss_api_setprinter
6850  * when updating a printer description.
6851  ********************************************************************/
6852
6853 static WERROR update_printer(struct pipes_struct *p,
6854                              struct policy_handle *handle,
6855                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6856                              struct spoolss_DeviceMode *devmode)
6857 {
6858         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6859         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6860         struct spoolss_PrinterInfo2 *old_printer;
6861         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6862         int snum;
6863         WERROR result = WERR_OK;
6864         TALLOC_CTX *tmp_ctx;
6865         struct dcerpc_binding_handle *b;
6866
6867         DEBUG(8,("update_printer\n"));
6868
6869         tmp_ctx = talloc_new(p->mem_ctx);
6870         if (tmp_ctx == NULL) {
6871                 return WERR_NOT_ENOUGH_MEMORY;
6872         }
6873
6874         if (!Printer) {
6875                 result = WERR_INVALID_HANDLE;
6876                 goto done;
6877         }
6878
6879         if (!get_printer_snum(p, handle, &snum, NULL)) {
6880                 result = WERR_INVALID_HANDLE;
6881                 goto done;
6882         }
6883
6884         result = winreg_printer_binding_handle(tmp_ctx,
6885                                                get_session_info_system(),
6886                                                p->msg_ctx,
6887                                                &b);
6888         if (!W_ERROR_IS_OK(result)) {
6889                 goto done;
6890         }
6891
6892         result = winreg_get_printer(tmp_ctx, b,
6893                                     lp_const_servicename(snum),
6894                                     &old_printer);
6895         if (!W_ERROR_IS_OK(result)) {
6896                 result = WERR_INVALID_HANDLE;
6897                 goto done;
6898         }
6899
6900         /* Do sanity check on the requested changes for Samba */
6901         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6902                 result = WERR_INVALID_PARAMETER;
6903                 goto done;
6904         }
6905
6906         /* FIXME!!! If the driver has changed we really should verify that
6907            it is installed before doing much else   --jerry */
6908
6909         /* Check calling user has permission to update printer description */
6910         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6911                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6912                 result = WERR_ACCESS_DENIED;
6913                 goto done;
6914         }
6915
6916         /* Call addprinter hook */
6917         /* Check changes to see if this is really needed */
6918
6919         if (*lp_addprinter_command(talloc_tos()) &&
6920                         (!strequal(printer->drivername, old_printer->drivername) ||
6921                          !strequal(printer->comment, old_printer->comment) ||
6922                          !strequal(printer->portname, old_printer->portname) ||
6923                          !strequal(printer->location, old_printer->location)) )
6924         {
6925                 char *raddr;
6926
6927                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6928                                                          p->mem_ctx);
6929                 if (raddr == NULL) {
6930                         return WERR_NOT_ENOUGH_MEMORY;
6931                 }
6932
6933                 /* add_printer_hook() will call reload_services() */
6934                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6935                                       printer, raddr,
6936                                       p->msg_ctx)) {
6937                         result = WERR_ACCESS_DENIED;
6938                         goto done;
6939                 }
6940         }
6941
6942         result = update_dsspooler(tmp_ctx,
6943                                   get_session_info_system(),
6944                                   p->msg_ctx,
6945                                   snum,
6946                                   printer,
6947                                   old_printer);
6948         if (!W_ERROR_IS_OK(result)) {
6949                 goto done;
6950         }
6951
6952         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6953
6954         if (devmode == NULL) {
6955                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6956         }
6957         result = winreg_update_printer(tmp_ctx, b,
6958                                        printer->sharename,
6959                                        printer_mask,
6960                                        printer,
6961                                        devmode,
6962                                        NULL);
6963
6964 done:
6965         talloc_free(tmp_ctx);
6966
6967         return result;
6968 }
6969
6970 /****************************************************************************
6971 ****************************************************************************/
6972 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6973                                            struct policy_handle *handle,
6974                                            struct spoolss_SetPrinterInfo7 *info7)
6975 {
6976 #ifdef HAVE_ADS
6977         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6978         WERROR result;
6979         int snum;
6980         struct printer_handle *Printer;
6981
6982         if ( lp_security() != SEC_ADS ) {
6983                 return WERR_INVALID_LEVEL;
6984         }
6985
6986         Printer = find_printer_index_by_hnd(p, handle);
6987
6988         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6989
6990         if (!Printer)
6991                 return WERR_INVALID_HANDLE;
6992
6993         if (!get_printer_snum(p, handle, &snum, NULL))
6994                 return WERR_INVALID_HANDLE;
6995
6996         result = winreg_get_printer_internal(p->mem_ctx,
6997                                     get_session_info_system(),
6998                                     p->msg_ctx,
6999                                     lp_servicename(talloc_tos(), snum),
7000                                     &pinfo2);
7001         if (!W_ERROR_IS_OK(result)) {
7002                 return WERR_INVALID_HANDLE;
7003         }
7004
7005         nt_printer_publish(pinfo2,
7006                            get_session_info_system(),
7007                            p->msg_ctx,
7008                            pinfo2,
7009                            info7->action);
7010
7011         TALLOC_FREE(pinfo2);
7012         return WERR_OK;
7013 #else
7014         return WERR_INVALID_LEVEL;
7015 #endif
7016 }
7017
7018 /********************************************************************
7019  ********************************************************************/
7020
7021 static WERROR update_printer_devmode(struct pipes_struct *p,
7022                                      struct policy_handle *handle,
7023                                      struct spoolss_DeviceMode *devmode)
7024 {
7025         int snum;
7026         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7027         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
7028
7029         DEBUG(8,("update_printer_devmode\n"));
7030
7031         if (!Printer) {
7032                 return WERR_INVALID_HANDLE;
7033         }
7034
7035         if (!get_printer_snum(p, handle, &snum, NULL)) {
7036                 return WERR_INVALID_HANDLE;
7037         }
7038
7039         /* Check calling user has permission to update printer description */
7040         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7041                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7042                 return WERR_ACCESS_DENIED;
7043         }
7044
7045         return winreg_update_printer_internal(p->mem_ctx,
7046                                      get_session_info_system(),
7047                                      p->msg_ctx,
7048                                      lp_const_servicename(snum),
7049                                      info2_mask,
7050                                      NULL,
7051                                      devmode,
7052                                      NULL);
7053 }
7054
7055
7056 /****************************************************************
7057  _spoolss_SetPrinter
7058 ****************************************************************/
7059
7060 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
7061                            struct spoolss_SetPrinter *r)
7062 {
7063         WERROR result;
7064
7065         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7066
7067         if (!Printer) {
7068                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
7069                         OUR_HANDLE(r->in.handle)));
7070                 return WERR_INVALID_HANDLE;
7071         }
7072
7073         /* check the level */
7074         switch (r->in.info_ctr->level) {
7075                 case 0:
7076                         return control_printer(r->in.handle, r->in.command, p);
7077                 case 2:
7078                         result = update_printer(p, r->in.handle,
7079                                                 r->in.info_ctr,
7080                                                 r->in.devmode_ctr->devmode);
7081                         if (!W_ERROR_IS_OK(result))
7082                                 return result;
7083                         if (r->in.secdesc_ctr->sd)
7084                                 result = update_printer_sec(r->in.handle, p,
7085                                                             r->in.secdesc_ctr);
7086                         return result;
7087                 case 3:
7088                         return update_printer_sec(r->in.handle, p,
7089                                                   r->in.secdesc_ctr);
7090                 case 4: {
7091                         struct spoolss_PrinterInfo2 *old_printer;
7092                         struct spoolss_SetPrinterInfo2 *set_old_printer;
7093                         struct spoolss_SetPrinterInfoCtr *info_ctr;
7094                         struct dcerpc_binding_handle *b;
7095                         int snum;
7096                         TALLOC_CTX *tmp_ctx;
7097
7098                         tmp_ctx = talloc_new(p->mem_ctx);
7099                         if (tmp_ctx == NULL) {
7100                                 return WERR_NOT_ENOUGH_MEMORY;
7101                         }
7102
7103                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7104                                 TALLOC_FREE(tmp_ctx);
7105                                 return WERR_INVALID_HANDLE;
7106                         }
7107
7108                         result = winreg_printer_binding_handle(tmp_ctx,
7109                                                                get_session_info_system(),
7110                                                                p->msg_ctx,
7111                                                                &b);
7112                         if (!W_ERROR_IS_OK(result)) {
7113                                 TALLOC_FREE(tmp_ctx);
7114                                 return result;
7115                         }
7116
7117                         result = winreg_get_printer(tmp_ctx, b,
7118                                                     lp_const_servicename(snum),
7119                                                     &old_printer);
7120                         if (!W_ERROR_IS_OK(result)) {
7121                                 TALLOC_FREE(tmp_ctx);
7122                                 return WERR_INVALID_HANDLE;
7123                         }
7124
7125                         old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
7126                         if (old_printer->servername == NULL) {
7127                                 TALLOC_FREE(tmp_ctx);
7128                                 return WERR_NOT_ENOUGH_MEMORY;
7129                         }
7130
7131                         old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
7132                         if (old_printer->printername == NULL) {
7133                                 TALLOC_FREE(tmp_ctx);
7134                                 return WERR_NOT_ENOUGH_MEMORY;
7135                         }
7136
7137                         old_printer->attributes = r->in.info_ctr->info.info4->attributes;
7138
7139                         set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
7140                         if (set_old_printer == NULL) {
7141                                 TALLOC_FREE(tmp_ctx);
7142                                 return WERR_NOT_ENOUGH_MEMORY;
7143                         }
7144
7145                         spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
7146
7147                         info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
7148                         if (info_ctr == NULL) {
7149                                 TALLOC_FREE(tmp_ctx);
7150                                 return WERR_NOT_ENOUGH_MEMORY;
7151                         }
7152
7153                         info_ctr->level = 2;
7154                         info_ctr->info.info2 = set_old_printer;
7155
7156                         result = update_printer(p, r->in.handle,
7157                                                 info_ctr,
7158                                                 r->in.devmode_ctr->devmode);
7159
7160                         if (!W_ERROR_IS_OK(result)) {
7161                                 TALLOC_FREE(tmp_ctx);
7162                                 return result;
7163                         }
7164
7165                         if (r->in.secdesc_ctr->sd) {
7166                                 result = update_printer_sec(r->in.handle, p,
7167                                                             r->in.secdesc_ctr);
7168                         }
7169
7170                         TALLOC_FREE(tmp_ctx);
7171                         return result;
7172                 }
7173                 case 7:
7174                         return publish_or_unpublish_printer(p, r->in.handle,
7175                                                             r->in.info_ctr->info.info7);
7176                 case 8:
7177                         return update_printer_devmode(p, r->in.handle,
7178                                                       r->in.devmode_ctr->devmode);
7179                 default:
7180                         return WERR_INVALID_LEVEL;
7181         }
7182 }
7183
7184 /****************************************************************
7185  _spoolss_FindClosePrinterNotify
7186 ****************************************************************/
7187
7188 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7189                                        struct spoolss_FindClosePrinterNotify *r)
7190 {
7191         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7192
7193         if (!Printer) {
7194                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7195                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7196                 return WERR_INVALID_HANDLE;
7197         }
7198
7199         if (Printer->notify.cli_chan != NULL &&
7200             Printer->notify.cli_chan->active_connections > 0) {
7201                 int snum = -1;
7202
7203                 if (Printer->printer_type == SPLHND_PRINTER) {
7204                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7205                                 return WERR_INVALID_HANDLE;
7206                         }
7207                 }
7208
7209                 srv_spoolss_replycloseprinter(snum, Printer);
7210         }
7211
7212         Printer->notify.flags=0;
7213         Printer->notify.options=0;
7214         Printer->notify.localmachine[0]='\0';
7215         Printer->notify.printerlocal=0;
7216         TALLOC_FREE(Printer->notify.option);
7217
7218         return WERR_OK;
7219 }
7220
7221 /****************************************************************
7222  _spoolss_AddJob
7223 ****************************************************************/
7224
7225 WERROR _spoolss_AddJob(struct pipes_struct *p,
7226                        struct spoolss_AddJob *r)
7227 {
7228         if (!r->in.buffer && (r->in.offered != 0)) {
7229                 return WERR_INVALID_PARAMETER;
7230         }
7231
7232         /* this is what a NT server returns for AddJob. AddJob must fail on
7233          * non-local printers */
7234
7235         if (r->in.level != 1) {
7236                 return WERR_INVALID_LEVEL;
7237         }
7238
7239         return WERR_INVALID_PARAMETER;
7240 }
7241
7242 /****************************************************************************
7243 fill_job_info1
7244 ****************************************************************************/
7245
7246 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7247                              struct spoolss_JobInfo1 *r,
7248                              const print_queue_struct *queue,
7249                              uint32_t jobid,
7250                              int position, int snum,
7251                              struct spoolss_PrinterInfo2 *pinfo2)
7252 {
7253         struct tm *t;
7254
7255         t = gmtime(&queue->time);
7256
7257         r->job_id               = jobid;
7258
7259         r->printer_name         = lp_servicename(mem_ctx, snum);
7260         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7261         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7262         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7263         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7264         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7265         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7266         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7267         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7268         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7269         r->text_status          = talloc_strdup(mem_ctx, "");
7270         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7271
7272         r->status               = nt_printj_status(queue->status);
7273         r->priority             = queue->priority;
7274         r->position             = position;
7275         r->total_pages          = queue->page_count;
7276         r->pages_printed        = 0; /* ??? */
7277
7278         init_systemtime(&r->submitted, t);
7279
7280         return WERR_OK;
7281 }
7282
7283 /****************************************************************************
7284 fill_job_info2
7285 ****************************************************************************/
7286
7287 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7288                              struct spoolss_JobInfo2 *r,
7289                              const print_queue_struct *queue,
7290                              uint32_t jobid,
7291                              int position, int snum,
7292                              struct spoolss_PrinterInfo2 *pinfo2,
7293                              struct spoolss_DeviceMode *devmode)
7294 {
7295         struct tm *t;
7296
7297         t = gmtime(&queue->time);
7298
7299         r->job_id               = jobid;
7300
7301         r->printer_name         = lp_servicename(mem_ctx, snum);
7302         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7303         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7304         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7305         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7306         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7307         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7308         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7309         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7310         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7311         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7312         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7313         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7314         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7315         r->parameters           = talloc_strdup(mem_ctx, "");
7316         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7317         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7318         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7319
7320         r->devmode              = devmode;
7321
7322         r->text_status          = talloc_strdup(mem_ctx, "");
7323         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7324
7325         r->secdesc              = NULL;
7326
7327         r->status               = nt_printj_status(queue->status);
7328         r->priority             = queue->priority;
7329         r->position             = position;
7330         r->start_time           = 0;
7331         r->until_time           = 0;
7332         r->total_pages          = queue->page_count;
7333         r->size                 = queue->size;
7334         init_systemtime(&r->submitted, t);
7335         r->time                 = 0;
7336         r->pages_printed        = 0; /* ??? */
7337
7338         return WERR_OK;
7339 }
7340
7341 /****************************************************************************
7342  Enumjobs at level 1.
7343 ****************************************************************************/
7344
7345 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7346                               const print_queue_struct *queue,
7347                               uint32_t num_queues, int snum,
7348                               struct spoolss_PrinterInfo2 *pinfo2,
7349                               union spoolss_JobInfo **info_p,
7350                               uint32_t *count)
7351 {
7352         union spoolss_JobInfo *info;
7353         int i;
7354         WERROR result = WERR_OK;
7355         uint32_t num_filled;
7356         struct tdb_print_db *pdb;
7357
7358         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7359         if (info == NULL) {
7360                 result = WERR_NOT_ENOUGH_MEMORY;
7361                 goto err_out;
7362         }
7363
7364         pdb = get_print_db_byname(pinfo2->sharename);
7365         if (pdb == NULL) {
7366                 result = WERR_INVALID_PARAMETER;
7367                 goto err_info_free;
7368         }
7369
7370         num_filled = 0;
7371         for (i = 0; i < num_queues; i++) {
7372                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7373                 if (jobid == (uint32_t)-1) {
7374                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7375                         continue;
7376                 }
7377
7378                 result = fill_job_info1(info,
7379                                         &info[num_filled].info1,
7380                                         &queue[i],
7381                                         jobid,
7382                                         i,
7383                                         snum,
7384                                         pinfo2);
7385                 if (!W_ERROR_IS_OK(result)) {
7386                         goto err_pdb_drop;
7387                 }
7388
7389                 num_filled++;
7390         }
7391
7392         release_print_db(pdb);
7393         *info_p = info;
7394         *count = num_filled;
7395
7396         return WERR_OK;
7397
7398 err_pdb_drop:
7399         release_print_db(pdb);
7400 err_info_free:
7401         TALLOC_FREE(info);
7402 err_out:
7403         *count = 0;
7404         return result;
7405 }
7406
7407 /****************************************************************************
7408  Enumjobs at level 2.
7409 ****************************************************************************/
7410
7411 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7412                               const print_queue_struct *queue,
7413                               uint32_t num_queues, int snum,
7414                               struct spoolss_PrinterInfo2 *pinfo2,
7415                               union spoolss_JobInfo **info_p,
7416                               uint32_t *count)
7417 {
7418         union spoolss_JobInfo *info;
7419         int i;
7420         WERROR result = WERR_OK;
7421         uint32_t num_filled;
7422         struct tdb_print_db *pdb;
7423
7424         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7425         if (info == NULL) {
7426                 result = WERR_NOT_ENOUGH_MEMORY;
7427                 goto err_out;
7428         }
7429
7430         pdb = get_print_db_byname(pinfo2->sharename);
7431         if (pdb == NULL) {
7432                 result = WERR_INVALID_PARAMETER;
7433                 goto err_info_free;
7434         }
7435
7436         num_filled = 0;
7437         for (i = 0; i< num_queues; i++) {
7438                 struct spoolss_DeviceMode *devmode;
7439                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7440                 if (jobid == (uint32_t)-1) {
7441                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7442                         continue;
7443                 }
7444
7445                 result = spoolss_create_default_devmode(info,
7446                                                         pinfo2->printername,
7447                                                         &devmode);
7448                 if (!W_ERROR_IS_OK(result)) {
7449                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7450                         goto err_pdb_drop;
7451                 }
7452
7453                 result = fill_job_info2(info,
7454                                         &info[num_filled].info2,
7455                                         &queue[i],
7456                                         jobid,
7457                                         i,
7458                                         snum,
7459                                         pinfo2,
7460                                         devmode);
7461                 if (!W_ERROR_IS_OK(result)) {
7462                         goto err_pdb_drop;
7463                 }
7464                 num_filled++;
7465         }
7466
7467         release_print_db(pdb);
7468         *info_p = info;
7469         *count = num_filled;
7470
7471         return WERR_OK;
7472
7473 err_pdb_drop:
7474         release_print_db(pdb);
7475 err_info_free:
7476         TALLOC_FREE(info);
7477 err_out:
7478         *count = 0;
7479         return result;
7480 }
7481
7482 /****************************************************************************
7483  Enumjobs at level 3.
7484 ****************************************************************************/
7485
7486 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7487                               const print_queue_struct *queue,
7488                               uint32_t num_queues, int snum,
7489                               struct spoolss_PrinterInfo2 *pinfo2,
7490                               union spoolss_JobInfo **info_p,
7491                               uint32_t *count)
7492 {
7493         union spoolss_JobInfo *info;
7494         int i;
7495         WERROR result = WERR_OK;
7496         uint32_t num_filled;
7497         struct tdb_print_db *pdb;
7498
7499         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7500         if (info == NULL) {
7501                 result = WERR_NOT_ENOUGH_MEMORY;
7502                 goto err_out;
7503         }
7504
7505         pdb = get_print_db_byname(pinfo2->sharename);
7506         if (pdb == NULL) {
7507                 result = WERR_INVALID_PARAMETER;
7508                 goto err_info_free;
7509         }
7510
7511         num_filled = 0;
7512         for (i = 0; i < num_queues; i++) {
7513                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7514                 if (jobid == (uint32_t)-1) {
7515                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7516                         continue;
7517                 }
7518
7519                 info[num_filled].info3.job_id = jobid;
7520                 /* next_job_id is overwritten on next iteration */
7521                 info[num_filled].info3.next_job_id = 0;
7522                 info[num_filled].info3.reserved = 0;
7523
7524                 if (num_filled > 0) {
7525                         info[num_filled - 1].info3.next_job_id = jobid;
7526                 }
7527                 num_filled++;
7528         }
7529
7530         release_print_db(pdb);
7531         *info_p = info;
7532         *count = num_filled;
7533
7534         return WERR_OK;
7535
7536 err_info_free:
7537         TALLOC_FREE(info);
7538 err_out:
7539         *count = 0;
7540         return result;
7541 }
7542
7543 /****************************************************************
7544  _spoolss_EnumJobs
7545 ****************************************************************/
7546
7547 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7548                          struct spoolss_EnumJobs *r)
7549 {
7550         WERROR result;
7551         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7552         int snum;
7553         print_status_struct prt_status;
7554         print_queue_struct *queue = NULL;
7555         uint32_t count;
7556
7557         /* that's an [in out] buffer */
7558
7559         if (!r->in.buffer && (r->in.offered != 0)) {
7560                 return WERR_INVALID_PARAMETER;
7561         }
7562
7563         if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7564                 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7565                 return WERR_INVALID_LEVEL;
7566         }
7567
7568         DEBUG(4,("_spoolss_EnumJobs\n"));
7569
7570         *r->out.needed = 0;
7571         *r->out.count = 0;
7572         *r->out.info = NULL;
7573
7574         /* lookup the printer snum and tdb entry */
7575
7576         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7577                 return WERR_INVALID_HANDLE;
7578         }
7579
7580         result = winreg_get_printer_internal(p->mem_ctx,
7581                                     get_session_info_system(),
7582                                     p->msg_ctx,
7583                                     lp_const_servicename(snum),
7584                                     &pinfo2);
7585         if (!W_ERROR_IS_OK(result)) {
7586                 return result;
7587         }
7588
7589         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7590         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7591                 count, prt_status.status, prt_status.message));
7592
7593         if (count == 0) {
7594                 SAFE_FREE(queue);
7595                 TALLOC_FREE(pinfo2);
7596                 return WERR_OK;
7597         }
7598
7599         switch (r->in.level) {
7600         case 1:
7601                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7602                                          pinfo2, r->out.info, r->out.count);
7603                 break;
7604         case 2:
7605                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7606                                          pinfo2, r->out.info, r->out.count);
7607                 break;
7608         case 3:
7609                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7610                                          pinfo2, r->out.info, r->out.count);
7611                 break;
7612         default:
7613                 SMB_ASSERT(false);      /* level checked on entry */
7614                 break;
7615         }
7616
7617         SAFE_FREE(queue);
7618         TALLOC_FREE(pinfo2);
7619
7620         if (!W_ERROR_IS_OK(result)) {
7621                 return result;
7622         }
7623
7624         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7625                                                      spoolss_EnumJobs,
7626                                                      *r->out.info, r->in.level,
7627                                                      *r->out.count);
7628         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7629         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7630
7631         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7632 }
7633
7634 /****************************************************************
7635  _spoolss_ScheduleJob
7636 ****************************************************************/
7637
7638 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7639                             struct spoolss_ScheduleJob *r)
7640 {
7641         return WERR_OK;
7642 }
7643
7644 /****************************************************************
7645 ****************************************************************/
7646
7647 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7648                                struct messaging_context *msg_ctx,
7649                                const char *printer_name,
7650                                uint32_t job_id,
7651                                struct spoolss_SetJobInfo1 *r)
7652 {
7653         char *old_doc_name;
7654
7655         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7656                 return WERR_INVALID_HANDLE;
7657         }
7658
7659         if (strequal(old_doc_name, r->document_name)) {
7660                 return WERR_OK;
7661         }
7662
7663         if (!print_job_set_name(server_event_context(), msg_ctx,
7664                                 printer_name, job_id, r->document_name)) {
7665                 return WERR_INVALID_HANDLE;
7666         }
7667
7668         return WERR_OK;
7669 }
7670
7671 /****************************************************************
7672  _spoolss_SetJob
7673 ****************************************************************/
7674
7675 WERROR _spoolss_SetJob(struct pipes_struct *p,
7676                        struct spoolss_SetJob *r)
7677 {
7678         const struct auth_session_info *session_info = p->session_info;
7679         int snum;
7680         WERROR errcode = WERR_INVALID_FUNCTION;
7681
7682         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7683                 return WERR_INVALID_HANDLE;
7684         }
7685
7686         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7687                 return WERR_INVALID_PRINTER_NAME;
7688         }
7689
7690         switch (r->in.command) {
7691         case SPOOLSS_JOB_CONTROL_CANCEL:
7692         case SPOOLSS_JOB_CONTROL_DELETE:
7693                 errcode = print_job_delete(session_info, p->msg_ctx,
7694                                            snum, r->in.job_id);
7695                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7696                         errcode = WERR_OK;
7697                 }
7698                 break;
7699         case SPOOLSS_JOB_CONTROL_PAUSE:
7700                 errcode = print_job_pause(session_info, p->msg_ctx,
7701                                           snum, r->in.job_id);
7702                 break;
7703         case SPOOLSS_JOB_CONTROL_RESTART:
7704         case SPOOLSS_JOB_CONTROL_RESUME:
7705                 errcode = print_job_resume(session_info, p->msg_ctx,
7706                                            snum, r->in.job_id);
7707                 break;
7708         case SPOOLSS_JOB_CONTROL_NOOP:
7709                 errcode = WERR_OK;
7710                 break;
7711         default:
7712                 return WERR_INVALID_LEVEL;
7713         }
7714
7715         if (!W_ERROR_IS_OK(errcode)) {
7716                 return errcode;
7717         }
7718
7719         if (r->in.ctr == NULL) {
7720                 return errcode;
7721         }
7722
7723         switch (r->in.ctr->level) {
7724         case 1:
7725                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7726                                            lp_const_servicename(snum),
7727                                            r->in.job_id,
7728                                            r->in.ctr->info.info1);
7729                 break;
7730         case 2:
7731         case 3:
7732         case 4:
7733         default:
7734                 return WERR_INVALID_LEVEL;
7735         }
7736
7737         return errcode;
7738 }
7739
7740 /****************************************************************************
7741  Enumerates all printer drivers by level and architecture.
7742 ****************************************************************************/
7743
7744 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7745                                                        const struct auth_session_info *session_info,
7746                                                        struct messaging_context *msg_ctx,
7747                                                        const char *servername,
7748                                                        const char *architecture,
7749                                                        uint32_t level,
7750                                                        union spoolss_DriverInfo **info_p,
7751                                                        uint32_t *count_p)
7752 {
7753         int i;
7754         uint32_t version;
7755         struct spoolss_DriverInfo8 *driver;
7756         union spoolss_DriverInfo *info = NULL;
7757         uint32_t count = 0;
7758         WERROR result = WERR_OK;
7759         uint32_t num_drivers;
7760         const char **drivers;
7761         struct dcerpc_binding_handle *b;
7762         TALLOC_CTX *tmp_ctx = NULL;
7763
7764         *count_p = 0;
7765         *info_p = NULL;
7766
7767         tmp_ctx = talloc_new(mem_ctx);
7768         if (!tmp_ctx) {
7769                 return WERR_NOT_ENOUGH_MEMORY;
7770         }
7771
7772         result = winreg_printer_binding_handle(tmp_ctx,
7773                                                session_info,
7774                                                msg_ctx,
7775                                                &b);
7776         if (!W_ERROR_IS_OK(result)) {
7777                 goto out;
7778         }
7779
7780         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7781                 result = winreg_get_driver_list(tmp_ctx, b,
7782                                                 architecture, version,
7783                                                 &num_drivers, &drivers);
7784                 if (!W_ERROR_IS_OK(result)) {
7785                         goto out;
7786                 }
7787                 DEBUG(4, ("we have:[%d] drivers in environment"
7788                           " [%s] and version [%d]\n",
7789                           num_drivers, architecture, version));
7790
7791                 if (num_drivers != 0) {
7792                         info = talloc_realloc(tmp_ctx, info,
7793                                                     union spoolss_DriverInfo,
7794                                                     count + num_drivers);
7795                         if (!info) {
7796                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7797                                         "failed to enlarge driver info buffer!\n"));
7798                                 result = WERR_NOT_ENOUGH_MEMORY;
7799                                 goto out;
7800                         }
7801                 }
7802
7803                 for (i = 0; i < num_drivers; i++) {
7804                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7805
7806                         result = winreg_get_driver(tmp_ctx, b,
7807                                                    architecture, drivers[i],
7808                                                    version, &driver);
7809                         if (!W_ERROR_IS_OK(result)) {
7810                                 goto out;
7811                         }
7812
7813                         switch (level) {
7814                         case 1:
7815                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7816                                                                    driver, servername);
7817                                 break;
7818                         case 2:
7819                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7820                                                                    driver, servername);
7821                                 break;
7822                         case 3:
7823                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7824                                                                    driver, servername);
7825                                 break;
7826                         case 4:
7827                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7828                                                                    driver, servername);
7829                                 break;
7830                         case 5:
7831                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7832                                                                    driver, servername);
7833                                 break;
7834                         case 6:
7835                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7836                                                                    driver, servername);
7837                                 break;
7838                         case 8:
7839                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7840                                                                    driver, servername);
7841                                 break;
7842                         default:
7843                                 result = WERR_INVALID_LEVEL;
7844                                 break;
7845                         }
7846
7847                         TALLOC_FREE(driver);
7848
7849                         if (!W_ERROR_IS_OK(result)) {
7850                                 goto out;
7851                         }
7852                 }
7853
7854                 count += num_drivers;
7855                 TALLOC_FREE(drivers);
7856         }
7857
7858 out:
7859         if (W_ERROR_IS_OK(result)) {
7860                 *info_p = talloc_move(mem_ctx, &info);
7861                 *count_p = count;
7862         }
7863
7864         talloc_free(tmp_ctx);
7865         return result;
7866 }
7867
7868 /****************************************************************************
7869  Enumerates all printer drivers by level.
7870 ****************************************************************************/
7871
7872 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7873                                        const struct auth_session_info *session_info,
7874                                        struct messaging_context *msg_ctx,
7875                                        const char *servername,
7876                                        const char *architecture,
7877                                        uint32_t level,
7878                                        union spoolss_DriverInfo **info_p,
7879                                        uint32_t *count_p)
7880 {
7881         uint32_t a,i;
7882         WERROR result = WERR_OK;
7883
7884         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7885
7886                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7887
7888                         union spoolss_DriverInfo *info = NULL;
7889                         uint32_t count = 0;
7890
7891                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7892                                                                           session_info,
7893                                                                           msg_ctx,
7894                                                                           servername,
7895                                                                           archi_table[a].long_archi,
7896                                                                           level,
7897                                                                           &info,
7898                                                                           &count);
7899                         if (!W_ERROR_IS_OK(result)) {
7900                                 continue;
7901                         }
7902
7903                         for (i=0; i < count; i++) {
7904                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7905                                              info[i], info_p, count_p);
7906                         }
7907                 }
7908
7909                 return result;
7910         }
7911
7912         return enumprinterdrivers_level_by_architecture(mem_ctx,
7913                                                         session_info,
7914                                                         msg_ctx,
7915                                                         servername,
7916                                                         architecture,
7917                                                         level,
7918                                                         info_p,
7919                                                         count_p);
7920 }
7921
7922 /****************************************************************
7923  _spoolss_EnumPrinterDrivers
7924 ****************************************************************/
7925
7926 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7927                                    struct spoolss_EnumPrinterDrivers *r)
7928 {
7929         const char *cservername;
7930         WERROR result;
7931
7932         /* that's an [in out] buffer */
7933
7934         if (!r->in.buffer && (r->in.offered != 0)) {
7935                 return WERR_INVALID_PARAMETER;
7936         }
7937
7938         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7939
7940         *r->out.needed = 0;
7941         *r->out.count = 0;
7942         *r->out.info = NULL;
7943
7944         cservername = canon_servername(r->in.server);
7945
7946         if (!is_myname_or_ipaddr(cservername)) {
7947                 return WERR_UNKNOWN_PRINTER_DRIVER;
7948         }
7949
7950         result = enumprinterdrivers_level(p->mem_ctx,
7951                                           get_session_info_system(),
7952                                           p->msg_ctx,
7953                                           cservername,
7954                                           r->in.environment,
7955                                           r->in.level,
7956                                           r->out.info,
7957                                           r->out.count);
7958         if (!W_ERROR_IS_OK(result)) {
7959                 return result;
7960         }
7961
7962         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7963                                                      spoolss_EnumPrinterDrivers,
7964                                                      *r->out.info, r->in.level,
7965                                                      *r->out.count);
7966         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7967         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7968
7969         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7970 }
7971
7972 /****************************************************************
7973  _spoolss_EnumForms
7974 ****************************************************************/
7975
7976 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7977                           struct spoolss_EnumForms *r)
7978 {
7979         WERROR result;
7980
7981         *r->out.count = 0;
7982         *r->out.needed = 0;
7983         *r->out.info = NULL;
7984
7985         /* that's an [in out] buffer */
7986
7987         if (!r->in.buffer && (r->in.offered != 0) ) {
7988                 return WERR_INVALID_PARAMETER;
7989         }
7990
7991         DEBUG(4,("_spoolss_EnumForms\n"));
7992         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7993         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7994
7995         switch (r->in.level) {
7996         case 1:
7997                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7998                                                    get_session_info_system(),
7999                                                    p->msg_ctx,
8000                                                    r->out.count,
8001                                                    r->out.info);
8002                 break;
8003         default:
8004                 result = WERR_INVALID_LEVEL;
8005                 break;
8006         }
8007
8008         if (!W_ERROR_IS_OK(result)) {
8009                 return result;
8010         }
8011
8012         if (*r->out.count == 0) {
8013                 return WERR_NO_MORE_ITEMS;
8014         }
8015
8016         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8017                                                      spoolss_EnumForms,
8018                                                      *r->out.info, r->in.level,
8019                                                      *r->out.count);
8020         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8021         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8022
8023         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8024 }
8025
8026 /****************************************************************
8027  _spoolss_GetForm
8028 ****************************************************************/
8029
8030 WERROR _spoolss_GetForm(struct pipes_struct *p,
8031                         struct spoolss_GetForm *r)
8032 {
8033         WERROR result;
8034
8035         /* that's an [in out] buffer */
8036
8037         if (!r->in.buffer && (r->in.offered != 0)) {
8038                 TALLOC_FREE(r->out.info);
8039                 return WERR_INVALID_PARAMETER;
8040         }
8041
8042         DEBUG(4,("_spoolss_GetForm\n"));
8043         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8044         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
8045
8046         switch (r->in.level) {
8047         case 1:
8048                 result = winreg_printer_getform1_internal(p->mem_ctx,
8049                                                  get_session_info_system(),
8050                                                  p->msg_ctx,
8051                                                  r->in.form_name,
8052                                                  &r->out.info->info1);
8053                 break;
8054         default:
8055                 result = WERR_INVALID_LEVEL;
8056                 break;
8057         }
8058
8059         if (!W_ERROR_IS_OK(result)) {
8060                 TALLOC_FREE(r->out.info);
8061                 return result;
8062         }
8063
8064         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
8065                                                r->out.info, r->in.level);
8066         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8067
8068         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8069 }
8070
8071 /****************************************************************************
8072 ****************************************************************************/
8073
8074 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
8075                           struct spoolss_PortInfo1 *r,
8076                           const char *name)
8077 {
8078         r->port_name = talloc_strdup(mem_ctx, name);
8079         W_ERROR_HAVE_NO_MEMORY(r->port_name);
8080
8081         return WERR_OK;
8082 }
8083
8084 /****************************************************************************
8085  TODO: This probably needs distinguish between TCP/IP and Local ports
8086  somehow.
8087 ****************************************************************************/
8088
8089 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
8090                           struct spoolss_PortInfo2 *r,
8091                           const char *name)
8092 {
8093         r->port_name = talloc_strdup(mem_ctx, name);
8094         W_ERROR_HAVE_NO_MEMORY(r->port_name);
8095
8096         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
8097         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8098
8099         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
8100         W_ERROR_HAVE_NO_MEMORY(r->description);
8101
8102         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
8103         r->reserved = 0;
8104
8105         return WERR_OK;
8106 }
8107
8108
8109 /****************************************************************************
8110  wrapper around the enumer ports command
8111 ****************************************************************************/
8112
8113 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
8114 {
8115         char *cmd = lp_enumports_command(talloc_tos());
8116         char **qlines = NULL;
8117         char *command = NULL;
8118         int numlines;
8119         int ret;
8120         int fd;
8121
8122         *count = 0;
8123         *lines = NULL;
8124
8125         /* if no hook then just fill in the default port */
8126
8127         if ( !*cmd ) {
8128                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
8129                         return WERR_NOT_ENOUGH_MEMORY;
8130                 }
8131                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
8132                         TALLOC_FREE(qlines);
8133                         return WERR_NOT_ENOUGH_MEMORY;
8134                 }
8135                 qlines[1] = NULL;
8136                 numlines = 1;
8137         }
8138         else {
8139                 /* we have a valid enumport command */
8140
8141                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
8142                 if (!command) {
8143                         return WERR_NOT_ENOUGH_MEMORY;
8144                 }
8145
8146                 DEBUG(10,("Running [%s]\n", command));
8147                 ret = smbrun(command, &fd, NULL);
8148                 DEBUG(10,("Returned [%d]\n", ret));
8149                 TALLOC_FREE(command);
8150                 if (ret != 0) {
8151                         if (fd != -1) {
8152                                 close(fd);
8153                         }
8154                         return WERR_ACCESS_DENIED;
8155                 }
8156
8157                 numlines = 0;
8158                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
8159                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8160                 close(fd);
8161         }
8162
8163         *count = numlines;
8164         *lines = qlines;
8165
8166         return WERR_OK;
8167 }
8168
8169 /****************************************************************************
8170  enumports level 1.
8171 ****************************************************************************/
8172
8173 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8174                                 union spoolss_PortInfo **info_p,
8175                                 uint32_t *count)
8176 {
8177         union spoolss_PortInfo *info = NULL;
8178         int i=0;
8179         WERROR result = WERR_OK;
8180         char **qlines = NULL;
8181         int numlines = 0;
8182
8183         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8184         if (!W_ERROR_IS_OK(result)) {
8185                 goto out;
8186         }
8187
8188         if (numlines) {
8189                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8190                 if (!info) {
8191                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8192                         result = WERR_NOT_ENOUGH_MEMORY;
8193                         goto out;
8194                 }
8195
8196                 for (i=0; i<numlines; i++) {
8197                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8198                         result = fill_port_1(info, &info[i].info1, qlines[i]);
8199                         if (!W_ERROR_IS_OK(result)) {
8200                                 goto out;
8201                         }
8202                 }
8203         }
8204         TALLOC_FREE(qlines);
8205
8206 out:
8207         if (!W_ERROR_IS_OK(result)) {
8208                 TALLOC_FREE(info);
8209                 TALLOC_FREE(qlines);
8210                 *count = 0;
8211                 *info_p = NULL;
8212                 return result;
8213         }
8214
8215         *info_p = info;
8216         *count = numlines;
8217
8218         return WERR_OK;
8219 }
8220
8221 /****************************************************************************
8222  enumports level 2.
8223 ****************************************************************************/
8224
8225 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8226                                 union spoolss_PortInfo **info_p,
8227                                 uint32_t *count)
8228 {
8229         union spoolss_PortInfo *info = NULL;
8230         int i=0;
8231         WERROR result = WERR_OK;
8232         char **qlines = NULL;
8233         int numlines = 0;
8234
8235         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8236         if (!W_ERROR_IS_OK(result)) {
8237                 goto out;
8238         }
8239
8240         if (numlines) {
8241                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8242                 if (!info) {
8243                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8244                         result = WERR_NOT_ENOUGH_MEMORY;
8245                         goto out;
8246                 }
8247
8248                 for (i=0; i<numlines; i++) {
8249                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8250                         result = fill_port_2(info, &info[i].info2, qlines[i]);
8251                         if (!W_ERROR_IS_OK(result)) {
8252                                 goto out;
8253                         }
8254                 }
8255         }
8256         TALLOC_FREE(qlines);
8257
8258 out:
8259         if (!W_ERROR_IS_OK(result)) {
8260                 TALLOC_FREE(info);
8261                 TALLOC_FREE(qlines);
8262                 *count = 0;
8263                 *info_p = NULL;
8264                 return result;
8265         }
8266
8267         *info_p = info;
8268         *count = numlines;
8269
8270         return WERR_OK;
8271 }
8272
8273 /****************************************************************
8274  _spoolss_EnumPorts
8275 ****************************************************************/
8276
8277 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8278                           struct spoolss_EnumPorts *r)
8279 {
8280         WERROR result;
8281
8282         /* that's an [in out] buffer */
8283
8284         if (!r->in.buffer && (r->in.offered != 0)) {
8285                 return WERR_INVALID_PARAMETER;
8286         }
8287
8288         DEBUG(4,("_spoolss_EnumPorts\n"));
8289
8290         *r->out.count = 0;
8291         *r->out.needed = 0;
8292         *r->out.info = NULL;
8293
8294         switch (r->in.level) {
8295         case 1:
8296                 result = enumports_level_1(p->mem_ctx, r->out.info,
8297                                            r->out.count);
8298                 break;
8299         case 2:
8300                 result = enumports_level_2(p->mem_ctx, r->out.info,
8301                                            r->out.count);
8302                 break;
8303         default:
8304                 return WERR_INVALID_LEVEL;
8305         }
8306
8307         if (!W_ERROR_IS_OK(result)) {
8308                 return result;
8309         }
8310
8311         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8312                                                      spoolss_EnumPorts,
8313                                                      *r->out.info, r->in.level,
8314                                                      *r->out.count);
8315         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8316         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8317
8318         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8319 }
8320
8321 /****************************************************************************
8322 ****************************************************************************/
8323
8324 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8325                                            const char *server,
8326                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8327                                            struct spoolss_DeviceMode *devmode,
8328                                            struct security_descriptor *secdesc,
8329                                            struct spoolss_UserLevelCtr *user_ctr,
8330                                            struct policy_handle *handle)
8331 {
8332         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8333         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8334         int     snum;
8335         WERROR err = WERR_OK;
8336
8337         /* samba does not have a concept of local, non-shared printers yet, so
8338          * make sure we always setup sharename - gd */
8339         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8340             (info2->printername != NULL && info2->printername[0] != '\0')) {
8341                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8342                         "no sharename has been set, setting printername %s as sharename\n",
8343                         info2->printername));
8344                 info2->sharename = info2->printername;
8345         }
8346
8347         /* check to see if the printer already exists */
8348         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8349                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8350                         info2->sharename));
8351                 return WERR_PRINTER_ALREADY_EXISTS;
8352         }
8353
8354         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8355                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8356                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8357                                 info2->printername));
8358                         return WERR_PRINTER_ALREADY_EXISTS;
8359                 }
8360         }
8361
8362         /* validate printer info struct */
8363         if (!info2->printername || strlen(info2->printername) == 0) {
8364                 return WERR_INVALID_PRINTER_NAME;
8365         }
8366         if (!info2->portname || strlen(info2->portname) == 0) {
8367                 return WERR_UNKNOWN_PORT;
8368         }
8369         if (!info2->drivername || strlen(info2->drivername) == 0) {
8370                 return WERR_UNKNOWN_PRINTER_DRIVER;
8371         }
8372         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8373                 return WERR_UNKNOWN_PRINTPROCESSOR;
8374         }
8375
8376         /* FIXME!!!  smbd should check to see if the driver is installed before
8377            trying to add a printer like this  --jerry */
8378
8379         if (*lp_addprinter_command(talloc_tos()) ) {
8380                 char *raddr;
8381
8382                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8383                                                          p->mem_ctx);
8384                 if (raddr == NULL) {
8385                         return WERR_NOT_ENOUGH_MEMORY;
8386                 }
8387
8388                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8389                                        info2, raddr,
8390                                        p->msg_ctx) ) {
8391                         return WERR_ACCESS_DENIED;
8392                 }
8393         } else {
8394                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8395                         "smb.conf parameter \"addprinter command\" is defined. This "
8396                         "parameter must exist for this call to succeed\n",
8397                         info2->sharename ));
8398         }
8399
8400         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8401                 return WERR_ACCESS_DENIED;
8402         }
8403
8404         /* you must be a printer admin to add a new printer */
8405         if (!W_ERROR_IS_OK(print_access_check(p->session_info,
8406                                               p->msg_ctx,
8407                                               snum,
8408                                               PRINTER_ACCESS_ADMINISTER))) {
8409                 return WERR_ACCESS_DENIED;
8410         }
8411
8412         /*
8413          * Do sanity check on the requested changes for Samba.
8414          */
8415
8416         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8417                 return WERR_INVALID_PARAMETER;
8418         }
8419
8420         if (devmode == NULL) {
8421                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8422         }
8423
8424         err = update_dsspooler(p->mem_ctx,
8425                                get_session_info_system(),
8426                                p->msg_ctx,
8427                                0,
8428                                info2,
8429                                NULL);
8430         if (!W_ERROR_IS_OK(err)) {
8431                 return err;
8432         }
8433
8434         err = winreg_update_printer_internal(p->mem_ctx,
8435                                     get_session_info_system(),
8436                                     p->msg_ctx,
8437                                     info2->sharename,
8438                                     info2_mask,
8439                                     info2,
8440                                     devmode,
8441                                     secdesc);
8442         if (!W_ERROR_IS_OK(err)) {
8443                 return err;
8444         }
8445
8446         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8447         if (!W_ERROR_IS_OK(err)) {
8448                 /* Handle open failed - remove addition. */
8449                 ZERO_STRUCTP(handle);
8450                 return err;
8451         }
8452
8453         return WERR_OK;
8454 }
8455
8456 /****************************************************************
8457  _spoolss_AddPrinterEx
8458 ****************************************************************/
8459
8460 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8461                              struct spoolss_AddPrinterEx *r)
8462 {
8463         switch (r->in.info_ctr->level) {
8464         case 1:
8465                 /* we don't handle yet */
8466                 /* but I know what to do ... */
8467                 return WERR_INVALID_LEVEL;
8468         case 2:
8469                 return spoolss_addprinterex_level_2(p, r->in.server,
8470                                                     r->in.info_ctr,
8471                                                     r->in.devmode_ctr->devmode,
8472                                                     r->in.secdesc_ctr->sd,
8473                                                     r->in.userlevel_ctr,
8474                                                     r->out.handle);
8475         default:
8476                 return WERR_INVALID_LEVEL;
8477         }
8478 }
8479
8480 /****************************************************************
8481  _spoolss_AddPrinter
8482 ****************************************************************/
8483
8484 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8485                            struct spoolss_AddPrinter *r)
8486 {
8487         struct spoolss_AddPrinterEx a;
8488         struct spoolss_UserLevelCtr userlevel_ctr;
8489
8490         ZERO_STRUCT(userlevel_ctr);
8491
8492         userlevel_ctr.level = 1;
8493
8494         a.in.server             = r->in.server;
8495         a.in.info_ctr           = r->in.info_ctr;
8496         a.in.devmode_ctr        = r->in.devmode_ctr;
8497         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8498         a.in.userlevel_ctr      = &userlevel_ctr;
8499         a.out.handle            = r->out.handle;
8500
8501         return _spoolss_AddPrinterEx(p, &a);
8502 }
8503
8504 /****************************************************************
8505  _spoolss_AddPrinterDriverEx
8506 ****************************************************************/
8507
8508 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8509                                    struct spoolss_AddPrinterDriverEx *r)
8510 {
8511         WERROR err = WERR_OK;
8512         const char *driver_name = NULL;
8513         uint32_t version;
8514         /*
8515          * we only support the semantics of AddPrinterDriver()
8516          * i.e. only copy files that are newer than existing ones
8517          */
8518
8519         if (r->in.flags == 0) {
8520                 return WERR_INVALID_PARAMETER;
8521         }
8522
8523         if (r->in.flags != APD_COPY_NEW_FILES) {
8524                 return WERR_ACCESS_DENIED;
8525         }
8526
8527         /* FIXME */
8528         if (r->in.info_ctr->level != 3 &&
8529             r->in.info_ctr->level != 6 &&
8530             r->in.info_ctr->level != 8) {
8531                 DEBUG(0,("%s: level %d not yet implemented\n", __func__,
8532                         r->in.info_ctr->level));
8533                 return WERR_INVALID_LEVEL;
8534         }
8535
8536         DEBUG(5,("Cleaning driver's information\n"));
8537         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8538         if (!W_ERROR_IS_OK(err))
8539                 goto done;
8540
8541         DEBUG(5,("Moving driver to final destination\n"));
8542         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8543         if (!W_ERROR_IS_OK(err)) {
8544                 goto done;
8545         }
8546
8547         err = winreg_add_driver_internal(p->mem_ctx,
8548                                 get_session_info_system(),
8549                                 p->msg_ctx,
8550                                 r->in.info_ctr,
8551                                 &driver_name,
8552                                 &version);
8553         if (!W_ERROR_IS_OK(err)) {
8554                 goto done;
8555         }
8556
8557         /*
8558          * I think this is where he DrvUpgradePrinter() hook would be
8559          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8560          * server.  Right now, we just need to send ourselves a message
8561          * to update each printer bound to this driver.   --jerry
8562          */
8563
8564         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8565                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8566                         __func__, driver_name));
8567         }
8568
8569 done:
8570         return err;
8571 }
8572
8573 /****************************************************************
8574  _spoolss_AddPrinterDriver
8575 ****************************************************************/
8576
8577 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8578                                  struct spoolss_AddPrinterDriver *r)
8579 {
8580         struct spoolss_AddPrinterDriverEx a;
8581
8582         switch (r->in.info_ctr->level) {
8583         case 2:
8584         case 3:
8585         case 4:
8586         case 5:
8587                 break;
8588         default:
8589                 return WERR_INVALID_LEVEL;
8590         }
8591
8592         a.in.servername         = r->in.servername;
8593         a.in.info_ctr           = r->in.info_ctr;
8594         a.in.flags              = APD_COPY_NEW_FILES;
8595
8596         return _spoolss_AddPrinterDriverEx(p, &a);
8597 }
8598
8599 /****************************************************************************
8600 ****************************************************************************/
8601
8602 struct _spoolss_paths {
8603         int type;
8604         const char *share;
8605         const char *dir;
8606 };
8607
8608 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8609
8610 static const struct _spoolss_paths spoolss_paths[]= {
8611         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8612         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8613 };
8614
8615 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8616                                           const char *servername,
8617                                           const char *environment,
8618                                           int component,
8619                                           char **path)
8620 {
8621         const char *pservername = NULL;
8622         const char *long_archi;
8623         const char *short_archi;
8624
8625         *path = NULL;
8626
8627         /* environment may be empty */
8628         if (environment && strlen(environment)) {
8629                 long_archi = environment;
8630         } else {
8631                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8632                                                   "spoolss", "architecture",
8633                                                   SPOOLSS_ARCHITECTURE_NT_X86);
8634         }
8635
8636         /* servername may be empty */
8637         if (servername && strlen(servername)) {
8638                 pservername = canon_servername(servername);
8639
8640                 if (!is_myname_or_ipaddr(pservername)) {
8641                         return WERR_INVALID_PARAMETER;
8642                 }
8643         }
8644
8645         if (!(short_archi = get_short_archi(long_archi))) {
8646                 return WERR_INVALID_ENVIRONMENT;
8647         }
8648
8649         switch (component) {
8650         case SPOOLSS_PRTPROCS_PATH:
8651         case SPOOLSS_DRIVER_PATH:
8652                 if (pservername) {
8653                         *path = talloc_asprintf(mem_ctx,
8654                                         "\\\\%s\\%s\\%s",
8655                                         pservername,
8656                                         spoolss_paths[component].share,
8657                                         short_archi);
8658                 } else {
8659                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8660                                         SPOOLSS_DEFAULT_SERVER_PATH,
8661                                         spoolss_paths[component].dir,
8662                                         short_archi);
8663                 }
8664                 break;
8665         default:
8666                 return WERR_INVALID_PARAMETER;
8667         }
8668
8669         if (!*path) {
8670                 return WERR_NOT_ENOUGH_MEMORY;
8671         }
8672
8673         return WERR_OK;
8674 }
8675
8676 /****************************************************************************
8677 ****************************************************************************/
8678
8679 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8680                                           const char *servername,
8681                                           const char *environment,
8682                                           struct spoolss_DriverDirectoryInfo1 *r)
8683 {
8684         WERROR werr;
8685         char *path = NULL;
8686
8687         werr = compose_spoolss_server_path(mem_ctx,
8688                                            servername,
8689                                            environment,
8690                                            SPOOLSS_DRIVER_PATH,
8691                                            &path);
8692         if (!W_ERROR_IS_OK(werr)) {
8693                 return werr;
8694         }
8695
8696         DEBUG(4,("printer driver directory: [%s]\n", path));
8697
8698         r->directory_name = path;
8699
8700         return WERR_OK;
8701 }
8702
8703 /****************************************************************
8704  _spoolss_GetPrinterDriverDirectory
8705 ****************************************************************/
8706
8707 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8708                                           struct spoolss_GetPrinterDriverDirectory *r)
8709 {
8710         WERROR werror;
8711
8712         /* that's an [in out] buffer */
8713
8714         if (!r->in.buffer && (r->in.offered != 0)) {
8715                 TALLOC_FREE(r->out.info);
8716                 return WERR_INVALID_PARAMETER;
8717         }
8718
8719         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8720                 r->in.level));
8721
8722         *r->out.needed = 0;
8723
8724         /* r->in.level is ignored */
8725
8726         werror = getprinterdriverdir_level_1(p->mem_ctx,
8727                                              r->in.server,
8728                                              r->in.environment,
8729                                              &r->out.info->info1);
8730         if (!W_ERROR_IS_OK(werror)) {
8731                 TALLOC_FREE(r->out.info);
8732                 return werror;
8733         }
8734
8735         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8736                                                r->out.info, r->in.level);
8737         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8738
8739         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8740 }
8741
8742 /****************************************************************
8743  _spoolss_EnumPrinterData
8744 ****************************************************************/
8745
8746 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8747                                 struct spoolss_EnumPrinterData *r)
8748 {
8749         WERROR result;
8750         struct spoolss_EnumPrinterDataEx r2;
8751         uint32_t count;
8752         struct spoolss_PrinterEnumValues *info, *val = NULL;
8753         uint32_t needed;
8754
8755         r2.in.handle    = r->in.handle;
8756         r2.in.key_name  = "PrinterDriverData";
8757         r2.in.offered   = 0;
8758         r2.out.count    = &count;
8759         r2.out.info     = &info;
8760         r2.out.needed   = &needed;
8761
8762         result = _spoolss_EnumPrinterDataEx(p, &r2);
8763         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8764                 r2.in.offered = needed;
8765                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8766         }
8767         if (!W_ERROR_IS_OK(result)) {
8768                 return result;
8769         }
8770
8771         /*
8772          * The NT machine wants to know the biggest size of value and data
8773          *
8774          * cf: MSDN EnumPrinterData remark section
8775          */
8776
8777         if (!r->in.value_offered && !r->in.data_offered) {
8778                 uint32_t biggest_valuesize = 0;
8779                 uint32_t biggest_datasize = 0;
8780                 int i, name_length;
8781
8782                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8783
8784                 for (i=0; i<count; i++) {
8785
8786                         name_length = strlen(info[i].value_name);
8787                         if (strlen(info[i].value_name) > biggest_valuesize) {
8788                                 biggest_valuesize = name_length;
8789                         }
8790
8791                         if (info[i].data_length > biggest_datasize) {
8792                                 biggest_datasize = info[i].data_length;
8793                         }
8794
8795                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8796                                 biggest_datasize));
8797                 }
8798
8799                 /* the value is an UNICODE string but real_value_size is the length
8800                    in bytes including the trailing 0 */
8801
8802                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8803                 *r->out.data_needed  = biggest_datasize;
8804
8805                 DEBUG(6,("final values: [%d], [%d]\n",
8806                         *r->out.value_needed, *r->out.data_needed));
8807
8808                 return WERR_OK;
8809         }
8810
8811         if (r->in.enum_index < count) {
8812                 val = &info[r->in.enum_index];
8813         }
8814
8815         if (val == NULL) {
8816                 /* out_value should default to "" or else NT4 has
8817                    problems unmarshalling the response */
8818
8819                 if (r->in.value_offered) {
8820                         *r->out.value_needed = 1;
8821                         r->out.value_name = talloc_strdup(r, "");
8822                         if (!r->out.value_name) {
8823                                 return WERR_NOT_ENOUGH_MEMORY;
8824                         }
8825                 } else {
8826                         r->out.value_name = NULL;
8827                         *r->out.value_needed = 0;
8828                 }
8829
8830                 /* the data is counted in bytes */
8831
8832                 *r->out.data_needed = r->in.data_offered;
8833
8834                 result = WERR_NO_MORE_ITEMS;
8835         } else {
8836                 /*
8837                  * the value is:
8838                  * - counted in bytes in the request
8839                  * - counted in UNICODE chars in the max reply
8840                  * - counted in bytes in the real size
8841                  *
8842                  * take a pause *before* coding not *during* coding
8843                  */
8844
8845                 /* name */
8846                 if (r->in.value_offered) {
8847                         r->out.value_name = talloc_strdup(r, val->value_name);
8848                         if (!r->out.value_name) {
8849                                 return WERR_NOT_ENOUGH_MEMORY;
8850                         }
8851                         *r->out.value_needed = val->value_name_len;
8852                 } else {
8853                         r->out.value_name = NULL;
8854                         *r->out.value_needed = 0;
8855                 }
8856
8857                 /* type */
8858
8859                 *r->out.type = val->type;
8860
8861                 /* data - counted in bytes */
8862
8863                 /*
8864                  * See the section "Dynamically Typed Query Parameters"
8865                  * in MS-RPRN.
8866                  */
8867
8868                 if (r->out.data && val->data && val->data->data &&
8869                                 val->data_length && r->in.data_offered) {
8870                         memcpy(r->out.data, val->data->data,
8871                                 MIN(val->data_length,r->in.data_offered));
8872                 }
8873
8874                 *r->out.data_needed = val->data_length;
8875
8876                 result = WERR_OK;
8877         }
8878
8879         return result;
8880 }
8881
8882 /****************************************************************
8883  _spoolss_SetPrinterData
8884 ****************************************************************/
8885
8886 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8887                                struct spoolss_SetPrinterData *r)
8888 {
8889         struct spoolss_SetPrinterDataEx r2;
8890
8891         r2.in.handle            = r->in.handle;
8892         r2.in.key_name          = "PrinterDriverData";
8893         r2.in.value_name        = r->in.value_name;
8894         r2.in.type              = r->in.type;
8895         r2.in.data              = r->in.data;
8896         r2.in.offered           = r->in.offered;
8897
8898         return _spoolss_SetPrinterDataEx(p, &r2);
8899 }
8900
8901 /****************************************************************
8902  _spoolss_ResetPrinter
8903 ****************************************************************/
8904
8905 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8906                              struct spoolss_ResetPrinter *r)
8907 {
8908         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8909         int             snum;
8910
8911         DEBUG(5,("_spoolss_ResetPrinter\n"));
8912
8913         /*
8914          * All we do is to check to see if the handle and queue is valid.
8915          * This call really doesn't mean anything to us because we only
8916          * support RAW printing.   --jerry
8917          */
8918
8919         if (!Printer) {
8920                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8921                         OUR_HANDLE(r->in.handle)));
8922                 return WERR_INVALID_HANDLE;
8923         }
8924
8925         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8926                 return WERR_INVALID_HANDLE;
8927
8928
8929         /* blindly return success */
8930         return WERR_OK;
8931 }
8932
8933 /****************************************************************
8934  _spoolss_DeletePrinterData
8935 ****************************************************************/
8936
8937 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8938                                   struct spoolss_DeletePrinterData *r)
8939 {
8940         struct spoolss_DeletePrinterDataEx r2;
8941
8942         r2.in.handle            = r->in.handle;
8943         r2.in.key_name          = "PrinterDriverData";
8944         r2.in.value_name        = r->in.value_name;
8945
8946         return _spoolss_DeletePrinterDataEx(p, &r2);
8947 }
8948
8949 /****************************************************************
8950  _spoolss_AddForm
8951 ****************************************************************/
8952
8953 WERROR _spoolss_AddForm(struct pipes_struct *p,
8954                         struct spoolss_AddForm *r)
8955 {
8956         struct spoolss_AddFormInfo1 *form;
8957         int snum = -1;
8958         WERROR status = WERR_OK;
8959         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8960         struct dcerpc_binding_handle *b;
8961         TALLOC_CTX *tmp_ctx = NULL;
8962
8963         DEBUG(5,("_spoolss_AddForm\n"));
8964
8965         if (!Printer) {
8966                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8967                         OUR_HANDLE(r->in.handle)));
8968                 return WERR_INVALID_HANDLE;
8969         }
8970
8971         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8972            and not a printer admin, then fail */
8973
8974         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8975             !security_token_has_privilege(p->session_info->security_token,
8976                                           SEC_PRIV_PRINT_OPERATOR)) {
8977                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8978                 return WERR_ACCESS_DENIED;
8979         }
8980
8981         if (r->in.info_ctr->level != 1) {
8982                 return WERR_INVALID_LEVEL;
8983         }
8984
8985         form = r->in.info_ctr->info.info1;
8986         if (!form) {
8987                 return WERR_INVALID_PARAMETER;
8988         }
8989
8990         switch (form->flags) {
8991         case SPOOLSS_FORM_USER:
8992         case SPOOLSS_FORM_BUILTIN:
8993         case SPOOLSS_FORM_PRINTER:
8994                 break;
8995         default:
8996                 return WERR_INVALID_PARAMETER;
8997         }
8998
8999         tmp_ctx = talloc_new(p->mem_ctx);
9000         if (!tmp_ctx) {
9001                 return WERR_NOT_ENOUGH_MEMORY;
9002         }
9003
9004         status = winreg_printer_binding_handle(tmp_ctx,
9005                                                get_session_info_system(),
9006                                                p->msg_ctx,
9007                                                &b);
9008         if (!W_ERROR_IS_OK(status)) {
9009                 goto done;
9010         }
9011
9012         status = winreg_printer_addform1(tmp_ctx, b, form);
9013         if (!W_ERROR_IS_OK(status)) {
9014                 goto done;
9015         }
9016
9017         /*
9018          * ChangeID must always be set if this is a printer
9019          */
9020         if (Printer->printer_type == SPLHND_PRINTER) {
9021                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9022                         status = WERR_INVALID_HANDLE;
9023                         goto done;
9024                 }
9025
9026                 status = winreg_printer_update_changeid(tmp_ctx, b,
9027                                                         lp_const_servicename(snum));
9028         }
9029
9030 done:
9031         talloc_free(tmp_ctx);
9032         return status;
9033 }
9034
9035 /****************************************************************
9036  _spoolss_DeleteForm
9037 ****************************************************************/
9038
9039 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
9040                            struct spoolss_DeleteForm *r)
9041 {
9042         const char *form_name = r->in.form_name;
9043         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9044         int snum = -1;
9045         WERROR status = WERR_OK;
9046         struct dcerpc_binding_handle *b;
9047         TALLOC_CTX *tmp_ctx = NULL;
9048
9049         DEBUG(5,("_spoolss_DeleteForm\n"));
9050
9051         if (!Printer) {
9052                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
9053                         OUR_HANDLE(r->in.handle)));
9054                 return WERR_INVALID_HANDLE;
9055         }
9056
9057         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9058             !security_token_has_privilege(p->session_info->security_token,
9059                                           SEC_PRIV_PRINT_OPERATOR)) {
9060                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
9061                 return WERR_ACCESS_DENIED;
9062         }
9063
9064         tmp_ctx = talloc_new(p->mem_ctx);
9065         if (!tmp_ctx) {
9066                 return WERR_NOT_ENOUGH_MEMORY;
9067         }
9068
9069         status = winreg_printer_binding_handle(tmp_ctx,
9070                                                get_session_info_system(),
9071                                                p->msg_ctx,
9072                                                &b);
9073         if (!W_ERROR_IS_OK(status)) {
9074                 goto done;
9075         }
9076
9077         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
9078         if (!W_ERROR_IS_OK(status)) {
9079                 goto done;
9080         }
9081
9082         /*
9083          * ChangeID must always be set if this is a printer
9084          */
9085         if (Printer->printer_type == SPLHND_PRINTER) {
9086                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9087                         status = WERR_INVALID_HANDLE;
9088                         goto done;
9089                 }
9090
9091                 status = winreg_printer_update_changeid(tmp_ctx, b,
9092                                                         lp_const_servicename(snum));
9093         }
9094
9095 done:
9096         talloc_free(tmp_ctx);
9097         return status;
9098 }
9099
9100 /****************************************************************
9101  _spoolss_SetForm
9102 ****************************************************************/
9103
9104 WERROR _spoolss_SetForm(struct pipes_struct *p,
9105                         struct spoolss_SetForm *r)
9106 {
9107         struct spoolss_AddFormInfo1 *form;
9108         const char *form_name = r->in.form_name;
9109         int snum = -1;
9110         WERROR status = WERR_OK;
9111         struct dcerpc_binding_handle *b;
9112         TALLOC_CTX *tmp_ctx = NULL;
9113
9114         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9115
9116         DEBUG(5,("_spoolss_SetForm\n"));
9117
9118         if (!Printer) {
9119                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
9120                         OUR_HANDLE(r->in.handle)));
9121                 return WERR_INVALID_HANDLE;
9122         }
9123
9124         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9125            and not a printer admin, then fail */
9126
9127         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9128              !security_token_has_privilege(p->session_info->security_token,
9129                                            SEC_PRIV_PRINT_OPERATOR)) {
9130                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
9131                 return WERR_ACCESS_DENIED;
9132         }
9133
9134         if (r->in.info_ctr->level != 1) {
9135                 return WERR_INVALID_LEVEL;
9136         }
9137
9138         form = r->in.info_ctr->info.info1;
9139         if (!form) {
9140                 return WERR_INVALID_PARAMETER;
9141         }
9142
9143         tmp_ctx = talloc_new(p->mem_ctx);
9144         if (!tmp_ctx) {
9145                 return WERR_NOT_ENOUGH_MEMORY;
9146         }
9147
9148         status = winreg_printer_binding_handle(tmp_ctx,
9149                                                get_session_info_system(),
9150                                                p->msg_ctx,
9151                                                &b);
9152         if (!W_ERROR_IS_OK(status)) {
9153                 goto done;
9154         }
9155
9156         status = winreg_printer_setform1(tmp_ctx, b,
9157                                          form_name,
9158                                          form);
9159         if (!W_ERROR_IS_OK(status)) {
9160                 goto done;
9161         }
9162
9163         /*
9164          * ChangeID must always be set if this is a printer
9165          */
9166         if (Printer->printer_type == SPLHND_PRINTER) {
9167                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9168                         status = WERR_INVALID_HANDLE;
9169                         goto done;
9170                 }
9171
9172                 status = winreg_printer_update_changeid(tmp_ctx, b,
9173                                                         lp_const_servicename(snum));
9174         }
9175
9176 done:
9177         talloc_free(tmp_ctx);
9178         return status;
9179 }
9180
9181 /****************************************************************************
9182  fill_print_processor1
9183 ****************************************************************************/
9184
9185 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9186                                     struct spoolss_PrintProcessorInfo1 *r,
9187                                     const char *print_processor_name)
9188 {
9189         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9190         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9191
9192         return WERR_OK;
9193 }
9194
9195 /****************************************************************************
9196  enumprintprocessors level 1.
9197 ****************************************************************************/
9198
9199 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9200                                           union spoolss_PrintProcessorInfo **info_p,
9201                                           uint32_t *count)
9202 {
9203         union spoolss_PrintProcessorInfo *info;
9204         WERROR result;
9205
9206         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9207         W_ERROR_HAVE_NO_MEMORY(info);
9208
9209         *count = 1;
9210
9211         result = fill_print_processor1(info, &info[0].info1, "winprint");
9212         if (!W_ERROR_IS_OK(result)) {
9213                 goto out;
9214         }
9215
9216  out:
9217         if (!W_ERROR_IS_OK(result)) {
9218                 TALLOC_FREE(info);
9219                 *count = 0;
9220                 return result;
9221         }
9222
9223         *info_p = info;
9224
9225         return WERR_OK;
9226 }
9227
9228 /****************************************************************
9229  _spoolss_EnumPrintProcessors
9230 ****************************************************************/
9231
9232 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9233                                     struct spoolss_EnumPrintProcessors *r)
9234 {
9235         WERROR result;
9236
9237         /* that's an [in out] buffer */
9238
9239         if (!r->in.buffer && (r->in.offered != 0)) {
9240                 return WERR_INVALID_PARAMETER;
9241         }
9242
9243         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9244
9245         /*
9246          * Enumerate the print processors ...
9247          *
9248          * Just reply with "winprint", to keep NT happy
9249          * and I can use my nice printer checker.
9250          */
9251
9252         *r->out.count = 0;
9253         *r->out.needed = 0;
9254         *r->out.info = NULL;
9255
9256         if (!get_short_archi(r->in.environment)) {
9257                 return WERR_INVALID_ENVIRONMENT;
9258         }
9259
9260         switch (r->in.level) {
9261         case 1:
9262                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9263                                                      r->out.count);
9264                 break;
9265         default:
9266                 return WERR_INVALID_LEVEL;
9267         }
9268
9269         if (!W_ERROR_IS_OK(result)) {
9270                 return result;
9271         }
9272
9273         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9274                                                      spoolss_EnumPrintProcessors,
9275                                                      *r->out.info, r->in.level,
9276                                                      *r->out.count);
9277         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9278         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9279
9280         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9281 }
9282
9283 /****************************************************************************
9284  fill_printprocdatatype1
9285 ****************************************************************************/
9286
9287 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9288                                       struct spoolss_PrintProcDataTypesInfo1 *r,
9289                                       const char *name_array)
9290 {
9291         r->name_array = talloc_strdup(mem_ctx, name_array);
9292         W_ERROR_HAVE_NO_MEMORY(r->name_array);
9293
9294         return WERR_OK;
9295 }
9296
9297 /****************************************************************************
9298  enumprintprocdatatypes level 1.
9299 ****************************************************************************/
9300
9301 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9302                                              union spoolss_PrintProcDataTypesInfo **info_p,
9303                                              uint32_t *count)
9304 {
9305         WERROR result;
9306         union spoolss_PrintProcDataTypesInfo *info;
9307
9308         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9309         W_ERROR_HAVE_NO_MEMORY(info);
9310
9311         *count = 1;
9312
9313         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9314         if (!W_ERROR_IS_OK(result)) {
9315                 goto out;
9316         }
9317
9318  out:
9319         if (!W_ERROR_IS_OK(result)) {
9320                 TALLOC_FREE(info);
9321                 *count = 0;
9322                 return result;
9323         }
9324
9325         *info_p = info;
9326
9327         return WERR_OK;
9328 }
9329
9330 /****************************************************************
9331  _spoolss_EnumPrintProcessorDataTypes
9332 ****************************************************************/
9333
9334 WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
9335                                             struct spoolss_EnumPrintProcessorDataTypes *r)
9336 {
9337         WERROR result;
9338
9339         /* that's an [in out] buffer */
9340
9341         if (!r->in.buffer && (r->in.offered != 0)) {
9342                 return WERR_INVALID_PARAMETER;
9343         }
9344
9345         DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
9346
9347         *r->out.count = 0;
9348         *r->out.needed = 0;
9349         *r->out.info = NULL;
9350
9351         if (r->in.print_processor_name == NULL ||
9352             !strequal(r->in.print_processor_name, "winprint")) {
9353                 return WERR_UNKNOWN_PRINTPROCESSOR;
9354         }
9355
9356         switch (r->in.level) {
9357         case 1:
9358                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9359                                                         r->out.count);
9360                 break;
9361         default:
9362                 return WERR_INVALID_LEVEL;
9363         }
9364
9365         if (!W_ERROR_IS_OK(result)) {
9366                 return result;
9367         }
9368
9369         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9370                                                      spoolss_EnumPrintProcessorDataTypes,
9371                                                      *r->out.info, r->in.level,
9372                                                      *r->out.count);
9373         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9374         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9375
9376         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9377 }
9378
9379 /****************************************************************************
9380  fill_monitor_1
9381 ****************************************************************************/
9382
9383 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9384                              struct spoolss_MonitorInfo1 *r,
9385                              const char *monitor_name)
9386 {
9387         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9388         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9389
9390         return WERR_OK;
9391 }
9392
9393 /****************************************************************************
9394  fill_monitor_2
9395 ****************************************************************************/
9396
9397 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9398                              struct spoolss_MonitorInfo2 *r,
9399                              const char *monitor_name,
9400                              const char *environment,
9401                              const char *dll_name)
9402 {
9403         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9404         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9405         r->environment                  = talloc_strdup(mem_ctx, environment);
9406         W_ERROR_HAVE_NO_MEMORY(r->environment);
9407         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9408         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9409
9410         return WERR_OK;
9411 }
9412
9413 /****************************************************************************
9414  enumprintmonitors level 1.
9415 ****************************************************************************/
9416
9417 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9418                                         union spoolss_MonitorInfo **info_p,
9419                                         uint32_t *count)
9420 {
9421         union spoolss_MonitorInfo *info;
9422         WERROR result = WERR_OK;
9423
9424         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9425         W_ERROR_HAVE_NO_MEMORY(info);
9426
9427         *count = 2;
9428
9429         result = fill_monitor_1(info, &info[0].info1,
9430                                 SPL_LOCAL_PORT);
9431         if (!W_ERROR_IS_OK(result)) {
9432                 goto out;
9433         }
9434
9435         result = fill_monitor_1(info, &info[1].info1,
9436                                 SPL_TCPIP_PORT);
9437         if (!W_ERROR_IS_OK(result)) {
9438                 goto out;
9439         }
9440
9441 out:
9442         if (!W_ERROR_IS_OK(result)) {
9443                 TALLOC_FREE(info);
9444                 *count = 0;
9445                 return result;
9446         }
9447
9448         *info_p = info;
9449
9450         return WERR_OK;
9451 }
9452
9453 /****************************************************************************
9454  enumprintmonitors level 2.
9455 ****************************************************************************/
9456
9457 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9458                                         union spoolss_MonitorInfo **info_p,
9459                                         uint32_t *count)
9460 {
9461         union spoolss_MonitorInfo *info;
9462         WERROR result = WERR_OK;
9463
9464         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9465         W_ERROR_HAVE_NO_MEMORY(info);
9466
9467         *count = 2;
9468
9469         result = fill_monitor_2(info, &info[0].info2,
9470                                 SPL_LOCAL_PORT,
9471                                 "Windows NT X86", /* FIXME */
9472                                 "localmon.dll");
9473         if (!W_ERROR_IS_OK(result)) {
9474                 goto out;
9475         }
9476
9477         result = fill_monitor_2(info, &info[1].info2,
9478                                 SPL_TCPIP_PORT,
9479                                 "Windows NT X86", /* FIXME */
9480                                 "tcpmon.dll");
9481         if (!W_ERROR_IS_OK(result)) {
9482                 goto out;
9483         }
9484
9485 out:
9486         if (!W_ERROR_IS_OK(result)) {
9487                 TALLOC_FREE(info);
9488                 *count = 0;
9489                 return result;
9490         }
9491
9492         *info_p = info;
9493
9494         return WERR_OK;
9495 }
9496
9497 /****************************************************************
9498  _spoolss_EnumMonitors
9499 ****************************************************************/
9500
9501 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9502                              struct spoolss_EnumMonitors *r)
9503 {
9504         WERROR result;
9505
9506         /* that's an [in out] buffer */
9507
9508         if (!r->in.buffer && (r->in.offered != 0)) {
9509                 return WERR_INVALID_PARAMETER;
9510         }
9511
9512         DEBUG(5,("_spoolss_EnumMonitors\n"));
9513
9514         /*
9515          * Enumerate the print monitors ...
9516          *
9517          * Just reply with "Local Port", to keep NT happy
9518          * and I can use my nice printer checker.
9519          */
9520
9521         *r->out.count = 0;
9522         *r->out.needed = 0;
9523         *r->out.info = NULL;
9524
9525         switch (r->in.level) {
9526         case 1:
9527                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9528                                                    r->out.count);
9529                 break;
9530         case 2:
9531                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9532                                                    r->out.count);
9533                 break;
9534         default:
9535                 return WERR_INVALID_LEVEL;
9536         }
9537
9538         if (!W_ERROR_IS_OK(result)) {
9539                 return result;
9540         }
9541
9542         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9543                                                      spoolss_EnumMonitors,
9544                                                      *r->out.info, r->in.level,
9545                                                      *r->out.count);
9546         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9547         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9548
9549         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9550 }
9551
9552 /****************************************************************************
9553 ****************************************************************************/
9554
9555 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9556                              const print_queue_struct *queue,
9557                              int count, int snum,
9558                              struct spoolss_PrinterInfo2 *pinfo2,
9559                              uint32_t jobid,
9560                              int sysjob,
9561                              struct spoolss_JobInfo1 *r)
9562 {
9563         int i = 0;
9564         bool found = false;
9565
9566         for (i=0; i<count; i++) {
9567                 if (queue[i].sysjob == sysjob) {
9568                         found = true;
9569                         break;
9570                 }
9571         }
9572
9573         if (found == false) {
9574                 /* NT treats not found as bad param... yet another bad choice */
9575                 return WERR_INVALID_PARAMETER;
9576         }
9577
9578         return fill_job_info1(mem_ctx,
9579                               r,
9580                               &queue[i],
9581                               jobid,
9582                               i,
9583                               snum,
9584                               pinfo2);
9585 }
9586
9587 /****************************************************************************
9588 ****************************************************************************/
9589
9590 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9591                              const print_queue_struct *queue,
9592                              int count, int snum,
9593                              struct spoolss_PrinterInfo2 *pinfo2,
9594                              uint32_t jobid,
9595                              int sysjob,
9596                              struct spoolss_JobInfo2 *r)
9597 {
9598         int i = 0;
9599         bool found = false;
9600         struct spoolss_DeviceMode *devmode;
9601         WERROR result;
9602
9603         for (i=0; i<count; i++) {
9604                 if (queue[i].sysjob == sysjob) {
9605                         found = true;
9606                         break;
9607                 }
9608         }
9609
9610         if (found == false) {
9611                 /* NT treats not found as bad param... yet another bad
9612                    choice */
9613                 return WERR_INVALID_PARAMETER;
9614         }
9615
9616         /*
9617          * if the print job does not have a DEVMODE associated with it,
9618          * just use the one for the printer. A NULL devicemode is not
9619          *  a failure condition
9620          */
9621
9622         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9623         if (!devmode) {
9624                 result = spoolss_create_default_devmode(mem_ctx,
9625                                                 pinfo2->printername,
9626                                                 &devmode);
9627                 if (!W_ERROR_IS_OK(result)) {
9628                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9629                         return result;
9630                 }
9631         }
9632
9633         return fill_job_info2(mem_ctx,
9634                               r,
9635                               &queue[i],
9636                               jobid,
9637                               i,
9638                               snum,
9639                               pinfo2,
9640                               devmode);
9641 }
9642
9643 /****************************************************************
9644  _spoolss_GetJob
9645 ****************************************************************/
9646
9647 WERROR _spoolss_GetJob(struct pipes_struct *p,
9648                        struct spoolss_GetJob *r)
9649 {
9650         WERROR result = WERR_OK;
9651         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9652         const char *svc_name;
9653         int sysjob;
9654         int snum;
9655         int count;
9656         struct tdb_print_db *pdb;
9657         print_queue_struct      *queue = NULL;
9658         print_status_struct prt_status;
9659
9660         /* that's an [in out] buffer */
9661
9662         if (!r->in.buffer && (r->in.offered != 0)) {
9663                 result = WERR_INVALID_PARAMETER;
9664                 goto err_jinfo_free;
9665         }
9666
9667         DEBUG(5,("_spoolss_GetJob\n"));
9668
9669         *r->out.needed = 0;
9670
9671         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9672                 result = WERR_INVALID_HANDLE;
9673                 goto err_jinfo_free;
9674         }
9675
9676         svc_name = lp_const_servicename(snum);
9677         if (svc_name == NULL) {
9678                 result = WERR_INVALID_PARAMETER;
9679                 goto err_jinfo_free;
9680         }
9681
9682         result = winreg_get_printer_internal(p->mem_ctx,
9683                                     get_session_info_system(),
9684                                     p->msg_ctx,
9685                                     svc_name,
9686                                     &pinfo2);
9687         if (!W_ERROR_IS_OK(result)) {
9688                 goto err_jinfo_free;
9689         }
9690
9691         pdb = get_print_db_byname(svc_name);
9692         if (pdb == NULL) {
9693                 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9694                 result = WERR_INVALID_PARAMETER;
9695                 goto err_pinfo_free;
9696         }
9697
9698         sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9699         release_print_db(pdb);
9700         if (sysjob == -1) {
9701                 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9702                 result = WERR_INVALID_PARAMETER;
9703                 goto err_pinfo_free;
9704         }
9705
9706         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9707
9708         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9709                      count, prt_status.status, prt_status.message));
9710
9711         switch (r->in.level) {
9712         case 1:
9713                 result = getjob_level_1(p->mem_ctx,
9714                                         queue, count, snum, pinfo2,
9715                                         r->in.job_id, sysjob,
9716                                         &r->out.info->info1);
9717                 break;
9718         case 2:
9719                 result = getjob_level_2(p->mem_ctx,
9720                                         queue, count, snum, pinfo2,
9721                                         r->in.job_id, sysjob,
9722                                         &r->out.info->info2);
9723                 break;
9724         default:
9725                 result = WERR_INVALID_LEVEL;
9726                 break;
9727         }
9728
9729         SAFE_FREE(queue);
9730         TALLOC_FREE(pinfo2);
9731
9732         if (!W_ERROR_IS_OK(result)) {
9733                 goto err_jinfo_free;
9734         }
9735
9736         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9737                                                                                    r->in.level);
9738         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9739
9740         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9741
9742 err_pinfo_free:
9743         TALLOC_FREE(pinfo2);
9744 err_jinfo_free:
9745         TALLOC_FREE(r->out.info);
9746         return result;
9747 }
9748
9749 /****************************************************************
9750  _spoolss_GetPrinterDataEx
9751 ****************************************************************/
9752
9753 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9754                                  struct spoolss_GetPrinterDataEx *r)
9755 {
9756
9757         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9758         const char *printer;
9759         int                     snum = 0;
9760         WERROR result = WERR_OK;
9761         DATA_BLOB blob;
9762         enum winreg_Type val_type = REG_NONE;
9763         uint8_t *val_data = NULL;
9764         uint32_t val_size = 0;
9765         struct dcerpc_binding_handle *b;
9766         TALLOC_CTX *tmp_ctx;
9767
9768         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9769
9770         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9771                 r->in.key_name, r->in.value_name));
9772
9773         /* in case of problem, return some default values */
9774
9775         *r->out.needed  = 0;
9776         *r->out.type    = REG_NONE;
9777
9778         tmp_ctx = talloc_new(p->mem_ctx);
9779         if (!tmp_ctx) {
9780                 return WERR_NOT_ENOUGH_MEMORY;
9781         }
9782
9783         if (!Printer) {
9784                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9785                         OUR_HANDLE(r->in.handle)));
9786                 result = WERR_INVALID_HANDLE;
9787                 goto done;
9788         }
9789
9790         /* Is the handle to a printer or to the server? */
9791
9792         if (Printer->printer_type == SPLHND_SERVER) {
9793
9794                 union spoolss_PrinterData data;
9795
9796                 result = getprinterdata_printer_server(tmp_ctx,
9797                                                        r->in.value_name,
9798                                                        r->out.type,
9799                                                        &data);
9800                 if (!W_ERROR_IS_OK(result)) {
9801                         goto done;
9802                 }
9803
9804                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9805                                                   *r->out.type, &data);
9806                 if (!W_ERROR_IS_OK(result)) {
9807                         goto done;
9808                 }
9809
9810                 *r->out.needed = blob.length;
9811
9812                 if (r->in.offered >= *r->out.needed) {
9813                         memcpy(r->out.data, blob.data, blob.length);
9814                 }
9815
9816                 result = WERR_OK;
9817                 goto done;
9818         }
9819
9820         /* check to see if the keyname is valid */
9821         if (!strlen(r->in.key_name)) {
9822                 result = WERR_INVALID_PARAMETER;
9823                 goto done;
9824         }
9825
9826         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9827                 result = WERR_INVALID_HANDLE;
9828                 goto done;
9829         }
9830         printer = lp_const_servicename(snum);
9831
9832         result = winreg_printer_binding_handle(tmp_ctx,
9833                                                get_session_info_system(),
9834                                                p->msg_ctx,
9835                                                &b);
9836         if (!W_ERROR_IS_OK(result)) {
9837                 goto done;
9838         }
9839
9840         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9841         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9842             strequal(r->in.value_name, "ChangeId")) {
9843                 *r->out.type = REG_DWORD;
9844                 *r->out.needed = 4;
9845                 if (r->in.offered >= *r->out.needed) {
9846                         uint32_t changeid = 0;
9847
9848                         result = winreg_printer_get_changeid(tmp_ctx, b,
9849                                                              printer,
9850                                                              &changeid);
9851                         if (!W_ERROR_IS_OK(result)) {
9852                                 goto done;
9853                         }
9854
9855                         SIVAL(r->out.data, 0, changeid);
9856                         result = WERR_OK;
9857                 }
9858                 goto done;
9859         }
9860
9861         result = winreg_get_printer_dataex(tmp_ctx, b,
9862                                            printer,
9863                                            r->in.key_name,
9864                                            r->in.value_name,
9865                                            &val_type,
9866                                            &val_data,
9867                                            &val_size);
9868         if (!W_ERROR_IS_OK(result)) {
9869                 goto done;
9870         }
9871
9872         *r->out.needed = val_size;
9873         *r->out.type = val_type;
9874
9875         if (r->in.offered >= *r->out.needed) {
9876                 memcpy(r->out.data, val_data, val_size);
9877         }
9878
9879 done:
9880         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9881
9882         if (W_ERROR_IS_OK(result)) {
9883                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9884         }
9885
9886         talloc_free(tmp_ctx);
9887         return result;
9888 }
9889
9890 /****************************************************************
9891  _spoolss_SetPrinterDataEx
9892 ****************************************************************/
9893
9894 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9895                                  struct spoolss_SetPrinterDataEx *r)
9896 {
9897         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9898         int                     snum = 0;
9899         WERROR                  result = WERR_OK;
9900         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9901         char                    *oid_string;
9902         struct dcerpc_binding_handle *b;
9903         TALLOC_CTX *tmp_ctx;
9904
9905         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9906
9907         /* From MSDN documentation of SetPrinterDataEx: pass request to
9908            SetPrinterData if key is "PrinterDriverData" */
9909
9910         if (!Printer) {
9911                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9912                         OUR_HANDLE(r->in.handle)));
9913                 return WERR_INVALID_HANDLE;
9914         }
9915
9916         if (Printer->printer_type == SPLHND_SERVER) {
9917                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9918                         "Not implemented for server handles yet\n"));
9919                 return WERR_INVALID_PARAMETER;
9920         }
9921
9922         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9923                 return WERR_INVALID_HANDLE;
9924         }
9925
9926         /*
9927          * Access check : NT returns "access denied" if you make a
9928          * SetPrinterData call without the necessary privildge.
9929          * we were originally returning OK if nothing changed
9930          * which made Win2k issue **a lot** of SetPrinterData
9931          * when connecting to a printer  --jerry
9932          */
9933
9934         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9935                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9936                         "change denied by handle access permissions\n"));
9937                 return WERR_ACCESS_DENIED;
9938         }
9939
9940         tmp_ctx = talloc_new(p->mem_ctx);
9941         if (!tmp_ctx) {
9942                 return WERR_NOT_ENOUGH_MEMORY;
9943         }
9944
9945         result = winreg_printer_binding_handle(tmp_ctx,
9946                                                get_session_info_system(),
9947                                                p->msg_ctx,
9948                                                &b);
9949         if (!W_ERROR_IS_OK(result)) {
9950                 goto done;
9951         }
9952
9953         result = winreg_get_printer(tmp_ctx, b,
9954                                     lp_servicename(talloc_tos(), snum),
9955                                     &pinfo2);
9956         if (!W_ERROR_IS_OK(result)) {
9957                 goto done;
9958         }
9959
9960         /* check for OID in valuename */
9961
9962         oid_string = strchr(r->in.value_name, ',');
9963         if (oid_string) {
9964                 *oid_string = '\0';
9965                 oid_string++;
9966         }
9967
9968         /* save the registry data */
9969
9970         result = winreg_set_printer_dataex(tmp_ctx, b,
9971                                            pinfo2->sharename,
9972                                            r->in.key_name,
9973                                            r->in.value_name,
9974                                            r->in.type,
9975                                            r->in.data,
9976                                            r->in.offered);
9977
9978         if (W_ERROR_IS_OK(result)) {
9979                 /* save the OID if one was specified */
9980                 if (oid_string) {
9981                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9982                                 r->in.key_name, SPOOL_OID_KEY);
9983                         if (!str) {
9984                                 result = WERR_NOT_ENOUGH_MEMORY;
9985                                 goto done;
9986                         }
9987
9988                         /*
9989                          * I'm not checking the status here on purpose.  Don't know
9990                          * if this is right, but I'm returning the status from the
9991                          * previous set_printer_dataex() call.  I have no idea if
9992                          * this is right.    --jerry
9993                          */
9994                         winreg_set_printer_dataex(tmp_ctx, b,
9995                                                   pinfo2->sharename,
9996                                                   str,
9997                                                   r->in.value_name,
9998                                                   REG_SZ,
9999                                                   (uint8_t *) oid_string,
10000                                                   strlen(oid_string) + 1);
10001                 }
10002
10003                 result = winreg_printer_update_changeid(tmp_ctx, b,
10004                                                         lp_const_servicename(snum));
10005
10006         }
10007
10008 done:
10009         talloc_free(tmp_ctx);
10010         return result;
10011 }
10012
10013 /****************************************************************
10014  _spoolss_DeletePrinterDataEx
10015 ****************************************************************/
10016
10017 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
10018                                     struct spoolss_DeletePrinterDataEx *r)
10019 {
10020         const char *printer;
10021         int             snum=0;
10022         WERROR          status = WERR_OK;
10023         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10024
10025         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
10026
10027         if (!Printer) {
10028                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
10029                         "Invalid handle (%s:%u:%u).\n",
10030                         OUR_HANDLE(r->in.handle)));
10031                 return WERR_INVALID_HANDLE;
10032         }
10033
10034         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10035                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
10036                         "printer properties change denied by handle\n"));
10037                 return WERR_ACCESS_DENIED;
10038         }
10039
10040         if (!r->in.value_name || !r->in.key_name) {
10041                 return WERR_NOT_ENOUGH_MEMORY;
10042         }
10043
10044         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10045                 return WERR_INVALID_HANDLE;
10046         }
10047         printer = lp_const_servicename(snum);
10048
10049         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
10050                                               get_session_info_system(),
10051                                               p->msg_ctx,
10052                                               printer,
10053                                               r->in.key_name,
10054                                               r->in.value_name);
10055         if (W_ERROR_IS_OK(status)) {
10056                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
10057                                                         get_session_info_system(),
10058                                                         p->msg_ctx,
10059                                                         printer);
10060         }
10061
10062         return status;
10063 }
10064
10065 /****************************************************************
10066  _spoolss_EnumPrinterKey
10067 ****************************************************************/
10068
10069 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
10070                                struct spoolss_EnumPrinterKey *r)
10071 {
10072         uint32_t        num_keys;
10073         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10074         int             snum = 0;
10075         WERROR          result = WERR_FILE_NOT_FOUND;
10076         const char **array = NULL;
10077         DATA_BLOB blob;
10078
10079         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
10080
10081         if (!Printer) {
10082                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
10083                         OUR_HANDLE(r->in.handle)));
10084                 return WERR_INVALID_HANDLE;
10085         }
10086
10087         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10088                 return WERR_INVALID_HANDLE;
10089         }
10090
10091         result = winreg_enum_printer_key_internal(p->mem_ctx,
10092                                          get_session_info_system(),
10093                                          p->msg_ctx,
10094                                          lp_const_servicename(snum),
10095                                          r->in.key_name,
10096                                          &num_keys,
10097                                          &array);
10098         if (!W_ERROR_IS_OK(result)) {
10099                 goto done;
10100         }
10101
10102         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
10103                 result = WERR_NOT_ENOUGH_MEMORY;
10104                 goto done;
10105         }
10106
10107         *r->out._ndr_size = r->in.offered / 2;
10108         *r->out.needed = blob.length;
10109
10110         if (r->in.offered < *r->out.needed) {
10111                 result = WERR_MORE_DATA;
10112         } else {
10113                 result = WERR_OK;
10114                 r->out.key_buffer->string_array = array;
10115         }
10116
10117  done:
10118         if (!W_ERROR_IS_OK(result)) {
10119                 TALLOC_FREE(array);
10120                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
10121                         *r->out.needed = 0;
10122                 }
10123         }
10124
10125         return result;
10126 }
10127
10128 /****************************************************************
10129  _spoolss_DeletePrinterKey
10130 ****************************************************************/
10131
10132 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
10133                                  struct spoolss_DeletePrinterKey *r)
10134 {
10135         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10136         int                     snum=0;
10137         WERROR                  status;
10138         const char *printer;
10139         struct dcerpc_binding_handle *b;
10140         TALLOC_CTX *tmp_ctx;
10141
10142         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10143
10144         if (!Printer) {
10145                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10146                         OUR_HANDLE(r->in.handle)));
10147                 return WERR_INVALID_HANDLE;
10148         }
10149
10150         /* if keyname == NULL, return error */
10151         if ( !r->in.key_name )
10152                 return WERR_INVALID_PARAMETER;
10153
10154         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10155                 return WERR_INVALID_HANDLE;
10156         }
10157
10158         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10159                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
10160                         "printer properties change denied by handle\n"));
10161                 return WERR_ACCESS_DENIED;
10162         }
10163
10164         printer = lp_const_servicename(snum);
10165
10166         tmp_ctx = talloc_new(p->mem_ctx);
10167         if (!tmp_ctx) {
10168                 return WERR_NOT_ENOUGH_MEMORY;
10169         }
10170
10171         status = winreg_printer_binding_handle(tmp_ctx,
10172                                                get_session_info_system(),
10173                                                p->msg_ctx,
10174                                                &b);
10175         if (!W_ERROR_IS_OK(status)) {
10176                 goto done;
10177         }
10178
10179         /* delete the key and all subkeys */
10180         status = winreg_delete_printer_key(tmp_ctx, b,
10181                                            printer,
10182                                            r->in.key_name);
10183         if (W_ERROR_IS_OK(status)) {
10184                 status = winreg_printer_update_changeid(tmp_ctx, b,
10185                                                         printer);
10186         }
10187
10188 done:
10189         talloc_free(tmp_ctx);
10190         return status;
10191 }
10192
10193 /****************************************************************
10194  _spoolss_EnumPrinterDataEx
10195 ****************************************************************/
10196
10197 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10198                                   struct spoolss_EnumPrinterDataEx *r)
10199 {
10200         uint32_t        count = 0;
10201         struct spoolss_PrinterEnumValues *info = NULL;
10202         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10203         int             snum;
10204         WERROR          result;
10205
10206         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10207
10208         *r->out.count = 0;
10209         *r->out.needed = 0;
10210         *r->out.info = NULL;
10211
10212         if (!Printer) {
10213                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10214                         OUR_HANDLE(r->in.handle)));
10215                 return WERR_INVALID_HANDLE;
10216         }
10217
10218         /*
10219          * first check for a keyname of NULL or "".  Win2k seems to send
10220          * this a lot and we should send back WERR_INVALID_PARAMETER
10221          * no need to spend time looking up the printer in this case.
10222          * --jerry
10223          */
10224
10225         if (!strlen(r->in.key_name)) {
10226                 result = WERR_INVALID_PARAMETER;
10227                 goto done;
10228         }
10229
10230         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10231                 return WERR_INVALID_HANDLE;
10232         }
10233
10234         /* now look for a match on the key name */
10235         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10236                                             get_session_info_system(),
10237                                             p->msg_ctx,
10238                                             lp_const_servicename(snum),
10239                                             r->in.key_name,
10240                                             &count,
10241                                             &info);
10242         if (!W_ERROR_IS_OK(result)) {
10243                 goto done;
10244         }
10245
10246 #if 0 /* FIXME - gd */
10247         /* housekeeping information in the reply */
10248
10249         /* Fix from Martin Zielinski <mz@seh.de> - ensure
10250          * the hand marshalled container size is a multiple
10251          * of 4 bytes for RPC alignment.
10252          */
10253
10254         if (needed % 4) {
10255                 needed += 4-(needed % 4);
10256         }
10257 #endif
10258         *r->out.count   = count;
10259         *r->out.info    = info;
10260
10261  done:
10262         if (!W_ERROR_IS_OK(result)) {
10263                 return result;
10264         }
10265
10266         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10267                                                spoolss_EnumPrinterDataEx,
10268                                                *r->out.info,
10269                                                *r->out.count);
10270         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10271         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10272
10273         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10274 }
10275
10276 /****************************************************************************
10277 ****************************************************************************/
10278
10279 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10280                                                  const char *servername,
10281                                                  const char *environment,
10282                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
10283 {
10284         WERROR werr;
10285         char *path = NULL;
10286
10287         werr = compose_spoolss_server_path(mem_ctx,
10288                                            servername,
10289                                            environment,
10290                                            SPOOLSS_PRTPROCS_PATH,
10291                                            &path);
10292         if (!W_ERROR_IS_OK(werr)) {
10293                 return werr;
10294         }
10295
10296         DEBUG(4,("print processor directory: [%s]\n", path));
10297
10298         r->directory_name = path;
10299
10300         return WERR_OK;
10301 }
10302
10303 /****************************************************************
10304  _spoolss_GetPrintProcessorDirectory
10305 ****************************************************************/
10306
10307 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10308                                            struct spoolss_GetPrintProcessorDirectory *r)
10309 {
10310         WERROR result;
10311         char *prnproc_share = NULL;
10312         bool prnproc_share_exists = false;
10313         int snum;
10314
10315         /* that's an [in out] buffer */
10316
10317         if (!r->in.buffer && (r->in.offered != 0)) {
10318                 result = WERR_INVALID_PARAMETER;
10319                 goto err_info_free;
10320         }
10321
10322         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10323                 r->in.level));
10324
10325         *r->out.needed = 0;
10326
10327         /* r->in.level is ignored */
10328
10329         /* We always should reply with a local print processor directory so that
10330          * users are not forced to have a [prnproc$] share on the Samba spoolss
10331          * server, if users decide to do so, lets announce it though - Guenther */
10332
10333         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10334         if (!prnproc_share) {
10335                 result = WERR_NOT_ENOUGH_MEMORY;
10336                 goto err_info_free;
10337         }
10338         if (snum != -1) {
10339                 prnproc_share_exists = true;
10340         }
10341
10342         result = getprintprocessordirectory_level_1(p->mem_ctx,
10343                                                     prnproc_share_exists ? r->in.server : NULL,
10344                                                     r->in.environment,
10345                                                     &r->out.info->info1);
10346         if (!W_ERROR_IS_OK(result)) {
10347                 goto err_info_free;
10348         }
10349
10350         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10351                                                                                    r->out.info, r->in.level);
10352         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10353
10354         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10355
10356 err_info_free:
10357         TALLOC_FREE(r->out.info);
10358         return result;
10359 }
10360
10361 /*******************************************************************
10362  ********************************************************************/
10363
10364 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10365                                const char *dllname)
10366 {
10367         enum ndr_err_code ndr_err;
10368         struct spoolss_MonitorUi ui;
10369
10370         ui.dll_name = dllname;
10371
10372         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10373                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10374         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10375                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10376         }
10377         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10378 }
10379
10380 /*******************************************************************
10381  Streams the monitor UI DLL name in UNICODE
10382 *******************************************************************/
10383
10384 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10385                                struct security_token *token, DATA_BLOB *in,
10386                                DATA_BLOB *out, uint32_t *needed)
10387 {
10388         const char *dllname = "tcpmonui.dll";
10389
10390         *needed = (strlen(dllname)+1) * 2;
10391
10392         if (out->length < *needed) {
10393                 return WERR_INSUFFICIENT_BUFFER;
10394         }
10395
10396         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10397                 return WERR_NOT_ENOUGH_MEMORY;
10398         }
10399
10400         return WERR_OK;
10401 }
10402
10403 /*******************************************************************
10404  ********************************************************************/
10405
10406 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10407                              struct spoolss_PortData1 *port1,
10408                              const DATA_BLOB *buf)
10409 {
10410         enum ndr_err_code ndr_err;
10411         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10412                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10413         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10414                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10415         }
10416         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10417 }
10418
10419 /*******************************************************************
10420  ********************************************************************/
10421
10422 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10423                              struct spoolss_PortData2 *port2,
10424                              const DATA_BLOB *buf)
10425 {
10426         enum ndr_err_code ndr_err;
10427         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10428                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10429         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10430                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10431         }
10432         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10433 }
10434
10435 /*******************************************************************
10436  Create a new TCP/IP port
10437 *******************************************************************/
10438
10439 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10440                              struct security_token *token, DATA_BLOB *in,
10441                              DATA_BLOB *out, uint32_t *needed)
10442 {
10443         struct spoolss_PortData1 port1;
10444         struct spoolss_PortData2 port2;
10445         char *device_uri = NULL;
10446         uint32_t version;
10447
10448         const char *portname;
10449         const char *hostaddress;
10450         const char *queue;
10451         uint32_t port_number;
10452         uint32_t protocol;
10453
10454         /* peek for spoolss_PortData version */
10455
10456         if (!in || (in->length < (128 + 4))) {
10457                 return WERR_GEN_FAILURE;
10458         }
10459
10460         version = IVAL(in->data, 128);
10461
10462         switch (version) {
10463                 case 1:
10464                         ZERO_STRUCT(port1);
10465
10466                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10467                                 return WERR_NOT_ENOUGH_MEMORY;
10468                         }
10469
10470                         portname        = port1.portname;
10471                         hostaddress     = port1.hostaddress;
10472                         queue           = port1.queue;
10473                         protocol        = port1.protocol;
10474                         port_number     = port1.port_number;
10475
10476                         break;
10477                 case 2:
10478                         ZERO_STRUCT(port2);
10479
10480                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10481                                 return WERR_NOT_ENOUGH_MEMORY;
10482                         }
10483
10484                         portname        = port2.portname;
10485                         hostaddress     = port2.hostaddress;
10486                         queue           = port2.queue;
10487                         protocol        = port2.protocol;
10488                         port_number     = port2.port_number;
10489
10490                         break;
10491                 default:
10492                         DEBUG(1,("xcvtcp_addport: "
10493                                 "unknown version of port_data: %d\n", version));
10494                         return WERR_UNKNOWN_PORT;
10495         }
10496
10497         /* create the device URI and call the add_port_hook() */
10498
10499         switch (protocol) {
10500         case PROTOCOL_RAWTCP_TYPE:
10501                 device_uri = talloc_asprintf(mem_ctx,
10502                                 "socket://%s:%d/", hostaddress,
10503                                 port_number);
10504                 break;
10505
10506         case PROTOCOL_LPR_TYPE:
10507                 device_uri = talloc_asprintf(mem_ctx,
10508                         "lpr://%s/%s", hostaddress, queue );
10509                 break;
10510
10511         default:
10512                 return WERR_UNKNOWN_PORT;
10513         }
10514
10515         if (!device_uri) {
10516                 return WERR_NOT_ENOUGH_MEMORY;
10517         }
10518
10519         return add_port_hook(mem_ctx, token, portname, device_uri);
10520 }
10521
10522 /*******************************************************************
10523 *******************************************************************/
10524
10525 struct xcv_api_table xcvtcp_cmds[] = {
10526         { "MonitorUI",  xcvtcp_monitorui },
10527         { "AddPort",    xcvtcp_addport},
10528         { NULL,         NULL }
10529 };
10530
10531 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10532                                      struct security_token *token, const char *command,
10533                                      DATA_BLOB *inbuf,
10534                                      DATA_BLOB *outbuf,
10535                                      uint32_t *needed )
10536 {
10537         int i;
10538
10539         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10540
10541         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10542                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10543                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10544         }
10545
10546         return WERR_INVALID_FUNCTION;
10547 }
10548
10549 /*******************************************************************
10550 *******************************************************************/
10551 #if 0   /* don't support management using the "Local Port" monitor */
10552
10553 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10554                                  struct security_token *token, DATA_BLOB *in,
10555                                  DATA_BLOB *out, uint32_t *needed)
10556 {
10557         const char *dllname = "localui.dll";
10558
10559         *needed = (strlen(dllname)+1) * 2;
10560
10561         if (out->length < *needed) {
10562                 return WERR_INSUFFICIENT_BUFFER;
10563         }
10564
10565         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10566                 return WERR_NOT_ENOUGH_MEMORY;
10567         }
10568
10569         return WERR_OK;
10570 }
10571
10572 /*******************************************************************
10573 *******************************************************************/
10574
10575 struct xcv_api_table xcvlocal_cmds[] = {
10576         { "MonitorUI",  xcvlocal_monitorui },
10577         { NULL,         NULL }
10578 };
10579 #else
10580 struct xcv_api_table xcvlocal_cmds[] = {
10581         { NULL,         NULL }
10582 };
10583 #endif
10584
10585
10586
10587 /*******************************************************************
10588 *******************************************************************/
10589
10590 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10591                                        struct security_token *token, const char *command,
10592                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10593                                        uint32_t *needed)
10594 {
10595         int i;
10596
10597         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10598
10599         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10600                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10601                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10602         }
10603         return WERR_INVALID_FUNCTION;
10604 }
10605
10606 /****************************************************************
10607  _spoolss_XcvData
10608 ****************************************************************/
10609
10610 WERROR _spoolss_XcvData(struct pipes_struct *p,
10611                         struct spoolss_XcvData *r)
10612 {
10613         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10614         DATA_BLOB out_data = data_blob_null;
10615         WERROR werror;
10616
10617         if (!Printer) {
10618                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10619                         OUR_HANDLE(r->in.handle)));
10620                 return WERR_INVALID_HANDLE;
10621         }
10622
10623         /* Has to be a handle to the TCP/IP port monitor */
10624
10625         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10626                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10627                 return WERR_INVALID_HANDLE;
10628         }
10629
10630         /* requires administrative access to the server */
10631
10632         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10633                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10634                 return WERR_ACCESS_DENIED;
10635         }
10636
10637         /* Allocate the outgoing buffer */
10638
10639         if (r->in.out_data_size) {
10640                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10641                 if (out_data.data == NULL) {
10642                         return WERR_NOT_ENOUGH_MEMORY;
10643                 }
10644         }
10645
10646         switch ( Printer->printer_type ) {
10647         case SPLHND_PORTMON_TCP:
10648                 werror = process_xcvtcp_command(p->mem_ctx,
10649                                                 p->session_info->security_token,
10650                                                 r->in.function_name,
10651                                                 &r->in.in_data, &out_data,
10652                                                 r->out.needed);
10653                 break;
10654         case SPLHND_PORTMON_LOCAL:
10655                 werror = process_xcvlocal_command(p->mem_ctx,
10656                                                   p->session_info->security_token,
10657                                                   r->in.function_name,
10658                                                   &r->in.in_data, &out_data,
10659                                                   r->out.needed);
10660                 break;
10661         default:
10662                 werror = WERR_INVALID_PRINT_MONITOR;
10663         }
10664
10665         if (!W_ERROR_IS_OK(werror)) {
10666                 return werror;
10667         }
10668
10669         *r->out.status_code = 0;
10670
10671         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10672                 memcpy(r->out.out_data, out_data.data,
10673                         MIN(r->in.out_data_size, out_data.length));
10674         }
10675
10676         return WERR_OK;
10677 }
10678
10679 /****************************************************************
10680  _spoolss_AddPrintProcessor
10681 ****************************************************************/
10682
10683 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10684                                   struct spoolss_AddPrintProcessor *r)
10685 {
10686         /* for now, just indicate success and ignore the add.  We'll
10687            automatically set the winprint processor for printer
10688            entries later.  Used to debug the LexMark Optra S 1855 PCL
10689            driver --jerry */
10690
10691         return WERR_OK;
10692 }
10693
10694 /****************************************************************
10695  _spoolss_AddPort
10696 ****************************************************************/
10697
10698 WERROR _spoolss_AddPort(struct pipes_struct *p,
10699                         struct spoolss_AddPort *r)
10700 {
10701         /* do what w2k3 does */
10702
10703         return WERR_NOT_SUPPORTED;
10704 }
10705
10706 /****************************************************************
10707  _spoolss_GetPrinterDriver
10708 ****************************************************************/
10709
10710 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10711                                  struct spoolss_GetPrinterDriver *r)
10712 {
10713         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10714         return WERR_NOT_SUPPORTED;
10715 }
10716
10717 /****************************************************************
10718  _spoolss_ReadPrinter
10719 ****************************************************************/
10720
10721 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10722                             struct spoolss_ReadPrinter *r)
10723 {
10724         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10725         return WERR_NOT_SUPPORTED;
10726 }
10727
10728 /****************************************************************
10729  _spoolss_WaitForPrinterChange
10730 ****************************************************************/
10731
10732 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10733                                      struct spoolss_WaitForPrinterChange *r)
10734 {
10735         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10736         return WERR_NOT_SUPPORTED;
10737 }
10738
10739 /****************************************************************
10740  _spoolss_ConfigurePort
10741 ****************************************************************/
10742
10743 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10744                               struct spoolss_ConfigurePort *r)
10745 {
10746         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10747         return WERR_NOT_SUPPORTED;
10748 }
10749
10750 /****************************************************************
10751  _spoolss_DeletePort
10752 ****************************************************************/
10753
10754 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10755                            struct spoolss_DeletePort *r)
10756 {
10757         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10758         return WERR_NOT_SUPPORTED;
10759 }
10760
10761 /****************************************************************
10762  _spoolss_CreatePrinterIC
10763 ****************************************************************/
10764
10765 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10766                                 struct spoolss_CreatePrinterIC *r)
10767 {
10768         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10769         return WERR_NOT_SUPPORTED;
10770 }
10771
10772 /****************************************************************
10773  _spoolss_PlayGDIScriptOnPrinterIC
10774 ****************************************************************/
10775
10776 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10777                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10778 {
10779         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10780         return WERR_NOT_SUPPORTED;
10781 }
10782
10783 /****************************************************************
10784  _spoolss_DeletePrinterIC
10785 ****************************************************************/
10786
10787 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10788                                 struct spoolss_DeletePrinterIC *r)
10789 {
10790         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10791         return WERR_NOT_SUPPORTED;
10792 }
10793
10794 /****************************************************************
10795  _spoolss_AddPrinterConnection
10796 ****************************************************************/
10797
10798 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10799                                      struct spoolss_AddPrinterConnection *r)
10800 {
10801         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10802         return WERR_NOT_SUPPORTED;
10803 }
10804
10805 /****************************************************************
10806  _spoolss_DeletePrinterConnection
10807 ****************************************************************/
10808
10809 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10810                                         struct spoolss_DeletePrinterConnection *r)
10811 {
10812         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10813         return WERR_NOT_SUPPORTED;
10814 }
10815
10816 /****************************************************************
10817  _spoolss_PrinterMessageBox
10818 ****************************************************************/
10819
10820 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10821                                   struct spoolss_PrinterMessageBox *r)
10822 {
10823         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10824         return WERR_NOT_SUPPORTED;
10825 }
10826
10827 /****************************************************************
10828  _spoolss_AddMonitor
10829 ****************************************************************/
10830
10831 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10832                            struct spoolss_AddMonitor *r)
10833 {
10834         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10835         return WERR_NOT_SUPPORTED;
10836 }
10837
10838 /****************************************************************
10839  _spoolss_DeleteMonitor
10840 ****************************************************************/
10841
10842 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10843                               struct spoolss_DeleteMonitor *r)
10844 {
10845         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10846         return WERR_NOT_SUPPORTED;
10847 }
10848
10849 /****************************************************************
10850  _spoolss_DeletePrintProcessor
10851 ****************************************************************/
10852
10853 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10854                                      struct spoolss_DeletePrintProcessor *r)
10855 {
10856         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10857         return WERR_NOT_SUPPORTED;
10858 }
10859
10860 /****************************************************************
10861  _spoolss_AddPrintProvidor
10862 ****************************************************************/
10863
10864 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10865                                  struct spoolss_AddPrintProvidor *r)
10866 {
10867         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10868         return WERR_NOT_SUPPORTED;
10869 }
10870
10871 /****************************************************************
10872  _spoolss_DeletePrintProvidor
10873 ****************************************************************/
10874
10875 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10876                                     struct spoolss_DeletePrintProvidor *r)
10877 {
10878         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10879         return WERR_NOT_SUPPORTED;
10880 }
10881
10882 /****************************************************************
10883  _spoolss_FindFirstPrinterChangeNotification
10884 ****************************************************************/
10885
10886 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10887                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10888 {
10889         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10890         return WERR_NOT_SUPPORTED;
10891 }
10892
10893 /****************************************************************
10894  _spoolss_FindNextPrinterChangeNotification
10895 ****************************************************************/
10896
10897 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10898                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10899 {
10900         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10901         return WERR_NOT_SUPPORTED;
10902 }
10903
10904 /****************************************************************
10905  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10906 ****************************************************************/
10907
10908 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10909                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10910 {
10911         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10912         return WERR_NOT_SUPPORTED;
10913 }
10914
10915 /****************************************************************
10916  _spoolss_ReplyOpenPrinter
10917 ****************************************************************/
10918
10919 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10920                                  struct spoolss_ReplyOpenPrinter *r)
10921 {
10922         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10923         return WERR_NOT_SUPPORTED;
10924 }
10925
10926 /****************************************************************
10927  _spoolss_RouterReplyPrinter
10928 ****************************************************************/
10929
10930 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10931                                    struct spoolss_RouterReplyPrinter *r)
10932 {
10933         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10934         return WERR_NOT_SUPPORTED;
10935 }
10936
10937 /****************************************************************
10938  _spoolss_ReplyClosePrinter
10939 ****************************************************************/
10940
10941 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10942                                   struct spoolss_ReplyClosePrinter *r)
10943 {
10944         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10945         return WERR_NOT_SUPPORTED;
10946 }
10947
10948 /****************************************************************
10949  _spoolss_AddPortEx
10950 ****************************************************************/
10951
10952 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10953                           struct spoolss_AddPortEx *r)
10954 {
10955         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10956         return WERR_NOT_SUPPORTED;
10957 }
10958
10959 /****************************************************************
10960  _spoolss_RouterFindFirstPrinterChangeNotification
10961 ****************************************************************/
10962
10963 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10964                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10965 {
10966         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10967         return WERR_NOT_SUPPORTED;
10968 }
10969
10970 /****************************************************************
10971  _spoolss_SpoolerInit
10972 ****************************************************************/
10973
10974 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10975                             struct spoolss_SpoolerInit *r)
10976 {
10977         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10978         return WERR_NOT_SUPPORTED;
10979 }
10980
10981 /****************************************************************
10982  _spoolss_ResetPrinterEx
10983 ****************************************************************/
10984
10985 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10986                                struct spoolss_ResetPrinterEx *r)
10987 {
10988         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10989         return WERR_NOT_SUPPORTED;
10990 }
10991
10992 /****************************************************************
10993  _spoolss_RouterReplyPrinterEx
10994 ****************************************************************/
10995
10996 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10997                                      struct spoolss_RouterReplyPrinterEx *r)
10998 {
10999         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11000         return WERR_NOT_SUPPORTED;
11001 }
11002
11003 /****************************************************************
11004  _spoolss_44
11005 ****************************************************************/
11006
11007 WERROR _spoolss_44(struct pipes_struct *p,
11008                    struct spoolss_44 *r)
11009 {
11010         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11011         return WERR_NOT_SUPPORTED;
11012 }
11013
11014 /****************************************************************
11015  _spoolss_SetPort
11016 ****************************************************************/
11017
11018 WERROR _spoolss_SetPort(struct pipes_struct *p,
11019                         struct spoolss_SetPort *r)
11020 {
11021         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11022         return WERR_NOT_SUPPORTED;
11023 }
11024
11025 /****************************************************************
11026  _spoolss_4a
11027 ****************************************************************/
11028
11029 WERROR _spoolss_4a(struct pipes_struct *p,
11030                    struct spoolss_4a *r)
11031 {
11032         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11033         return WERR_NOT_SUPPORTED;
11034 }
11035
11036 /****************************************************************
11037  _spoolss_4b
11038 ****************************************************************/
11039
11040 WERROR _spoolss_4b(struct pipes_struct *p,
11041                    struct spoolss_4b *r)
11042 {
11043         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11044         return WERR_NOT_SUPPORTED;
11045 }
11046
11047 /****************************************************************
11048  _spoolss_4c
11049 ****************************************************************/
11050
11051 WERROR _spoolss_4c(struct pipes_struct *p,
11052                    struct spoolss_4c *r)
11053 {
11054         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11055         return WERR_NOT_SUPPORTED;
11056 }
11057
11058 /****************************************************************
11059  _spoolss_53
11060 ****************************************************************/
11061
11062 WERROR _spoolss_53(struct pipes_struct *p,
11063                    struct spoolss_53 *r)
11064 {
11065         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11066         return WERR_NOT_SUPPORTED;
11067 }
11068
11069 /****************************************************************
11070  _spoolss_AddPerMachineConnection
11071 ****************************************************************/
11072
11073 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
11074                                         struct spoolss_AddPerMachineConnection *r)
11075 {
11076         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11077         return WERR_NOT_SUPPORTED;
11078 }
11079
11080 /****************************************************************
11081  _spoolss_DeletePerMachineConnection
11082 ****************************************************************/
11083
11084 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
11085                                            struct spoolss_DeletePerMachineConnection *r)
11086 {
11087         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11088         return WERR_NOT_SUPPORTED;
11089 }
11090
11091 /****************************************************************
11092  _spoolss_EnumPerMachineConnections
11093 ****************************************************************/
11094
11095 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
11096                                           struct spoolss_EnumPerMachineConnections *r)
11097 {
11098         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11099         return WERR_NOT_SUPPORTED;
11100 }
11101
11102 /****************************************************************
11103  _spoolss_5a
11104 ****************************************************************/
11105
11106 WERROR _spoolss_5a(struct pipes_struct *p,
11107                    struct spoolss_5a *r)
11108 {
11109         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11110         return WERR_NOT_SUPPORTED;
11111 }
11112
11113 /****************************************************************
11114  _spoolss_5b
11115 ****************************************************************/
11116
11117 WERROR _spoolss_5b(struct pipes_struct *p,
11118                    struct spoolss_5b *r)
11119 {
11120         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11121         return WERR_NOT_SUPPORTED;
11122 }
11123
11124 /****************************************************************
11125  _spoolss_5c
11126 ****************************************************************/
11127
11128 WERROR _spoolss_5c(struct pipes_struct *p,
11129                    struct spoolss_5c *r)
11130 {
11131         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11132         return WERR_NOT_SUPPORTED;
11133 }
11134
11135 /****************************************************************
11136  _spoolss_5d
11137 ****************************************************************/
11138
11139 WERROR _spoolss_5d(struct pipes_struct *p,
11140                    struct spoolss_5d *r)
11141 {
11142         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11143         return WERR_NOT_SUPPORTED;
11144 }
11145
11146 /****************************************************************
11147  _spoolss_5e
11148 ****************************************************************/
11149
11150 WERROR _spoolss_5e(struct pipes_struct *p,
11151                    struct spoolss_5e *r)
11152 {
11153         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11154         return WERR_NOT_SUPPORTED;
11155 }
11156
11157 /****************************************************************
11158  _spoolss_5f
11159 ****************************************************************/
11160
11161 WERROR _spoolss_5f(struct pipes_struct *p,
11162                    struct spoolss_5f *r)
11163 {
11164         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11165         return WERR_NOT_SUPPORTED;
11166 }
11167
11168 /****************************************************************
11169  _spoolss_60
11170 ****************************************************************/
11171
11172 WERROR _spoolss_60(struct pipes_struct *p,
11173                    struct spoolss_60 *r)
11174 {
11175         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11176         return WERR_NOT_SUPPORTED;
11177 }
11178
11179 /****************************************************************
11180  _spoolss_SendRecvBidiData
11181 ****************************************************************/
11182
11183 WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
11184                                  struct spoolss_SendRecvBidiData *r)
11185 {
11186         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11187         return WERR_NOT_SUPPORTED;
11188 }
11189
11190 /****************************************************************
11191  _spoolss_62
11192 ****************************************************************/
11193
11194 WERROR _spoolss_62(struct pipes_struct *p,
11195                    struct spoolss_62 *r)
11196 {
11197         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11198         return WERR_NOT_SUPPORTED;
11199 }
11200
11201 /****************************************************************
11202  _spoolss_63
11203 ****************************************************************/
11204
11205 WERROR _spoolss_63(struct pipes_struct *p,
11206                    struct spoolss_63 *r)
11207 {
11208         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11209         return WERR_NOT_SUPPORTED;
11210 }
11211
11212 /****************************************************************
11213  _spoolss_64
11214 ****************************************************************/
11215
11216 WERROR _spoolss_64(struct pipes_struct *p,
11217                    struct spoolss_64 *r)
11218 {
11219         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11220         return WERR_NOT_SUPPORTED;
11221 }
11222
11223 /****************************************************************
11224  _spoolss_65
11225 ****************************************************************/
11226
11227 WERROR _spoolss_65(struct pipes_struct *p,
11228                    struct spoolss_65 *r)
11229 {
11230         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11231         return WERR_NOT_SUPPORTED;
11232 }
11233
11234 /****************************************************************
11235  _spoolss_GetCorePrinterDrivers
11236 ****************************************************************/
11237
11238 HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11239                                        struct spoolss_GetCorePrinterDrivers *r)
11240 {
11241         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11242         return HRES_ERROR_NOT_SUPPORTED;
11243 }
11244
11245 /****************************************************************
11246  _spoolss_67
11247 ****************************************************************/
11248
11249 WERROR _spoolss_67(struct pipes_struct *p,
11250                    struct spoolss_67 *r)
11251 {
11252         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11253         return WERR_NOT_SUPPORTED;
11254 }
11255
11256 /****************************************************************
11257  _spoolss_GetPrinterDriverPackagePath
11258 ****************************************************************/
11259
11260 HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11261                                              struct spoolss_GetPrinterDriverPackagePath *r)
11262 {
11263         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11264         return HRES_ERROR_NOT_SUPPORTED;
11265 }
11266
11267 /****************************************************************
11268  _spoolss_69
11269 ****************************************************************/
11270
11271 WERROR _spoolss_69(struct pipes_struct *p,
11272                    struct spoolss_69 *r)
11273 {
11274         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11275         return WERR_NOT_SUPPORTED;
11276 }
11277
11278 /****************************************************************
11279  _spoolss_6a
11280 ****************************************************************/
11281
11282 WERROR _spoolss_6a(struct pipes_struct *p,
11283                    struct spoolss_6a *r)
11284 {
11285         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11286         return WERR_NOT_SUPPORTED;
11287 }
11288
11289 /****************************************************************
11290  _spoolss_6b
11291 ****************************************************************/
11292
11293 WERROR _spoolss_6b(struct pipes_struct *p,
11294                    struct spoolss_6b *r)
11295 {
11296         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11297         return WERR_NOT_SUPPORTED;
11298 }
11299
11300 /****************************************************************
11301  _spoolss_6c
11302 ****************************************************************/
11303
11304 WERROR _spoolss_6c(struct pipes_struct *p,
11305                    struct spoolss_6c *r)
11306 {
11307         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11308         return WERR_NOT_SUPPORTED;
11309 }
11310
11311 /****************************************************************
11312  _spoolss_6d
11313 ****************************************************************/
11314
11315 WERROR _spoolss_6d(struct pipes_struct *p,
11316                    struct spoolss_6d *r)
11317 {
11318         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11319         return WERR_NOT_SUPPORTED;
11320 }
11321
11322 /****************************************************************
11323  _spoolss_GetJobNamedPropertyValue
11324 ****************************************************************/
11325
11326 WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
11327                                          struct spoolss_GetJobNamedPropertyValue *r)
11328 {
11329         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11330         return WERR_NOT_SUPPORTED;
11331 }
11332
11333 /****************************************************************
11334  _spoolss_SetJobNamedProperty
11335 ****************************************************************/
11336
11337 WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
11338                                     struct spoolss_SetJobNamedProperty *r)
11339 {
11340         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11341         return WERR_NOT_SUPPORTED;
11342 }
11343
11344 /****************************************************************
11345  _spoolss_DeleteJobNamedProperty
11346 ****************************************************************/
11347
11348 WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
11349                                        struct spoolss_DeleteJobNamedProperty *r)
11350 {
11351         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11352         return WERR_NOT_SUPPORTED;
11353 }
11354
11355 /****************************************************************
11356  _spoolss_EnumJobNamedProperties
11357 ****************************************************************/
11358
11359 WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
11360                                        struct spoolss_EnumJobNamedProperties *r)
11361 {
11362         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11363         return WERR_NOT_SUPPORTED;
11364 }
11365
11366 /****************************************************************
11367  _spoolss_72
11368 ****************************************************************/
11369
11370 WERROR _spoolss_72(struct pipes_struct *p,
11371                    struct spoolss_72 *r)
11372 {
11373         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11374         return WERR_NOT_SUPPORTED;
11375 }
11376
11377 /****************************************************************
11378  _spoolss_73
11379 ****************************************************************/
11380
11381 WERROR _spoolss_73(struct pipes_struct *p,
11382                    struct spoolss_73 *r)
11383 {
11384         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11385         return WERR_NOT_SUPPORTED;
11386 }
11387
11388 /****************************************************************
11389  _spoolss_RpcLogJobInfoForBranchOffice
11390 ****************************************************************/
11391
11392 WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
11393                                           struct spoolss_LogJobInfoForBranchOffice *r)
11394 {
11395         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11396         return WERR_NOT_SUPPORTED;
11397 }