80d30cffbbf129fdf7cea2535e11a036e50679b9
[samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "include/printing.h"
42 #include "secrets.h"
43 #include "../librpc/gen_ndr/netlogon.h"
44 #include "rpc_misc.h"
45 #include "printing/notify.h"
46 #include "serverid.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "smbd/globals.h"
50 #include "auth.h"
51 #include "messages.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
53 #include "util_tdb.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
58 #include "../libcli/smb/smbXcli_base.h"
59 #include "rpc_server/spoolss/srv_spoolss_handle.h"
60
61 /* macros stolen from s4 spoolss server */
62 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
63         ((info)?ndr_size_##fn(info, level, 0):0)
64
65 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
66         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
67
68 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
69         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
70
71 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
72
73 #undef DBGC_CLASS
74 #define DBGC_CLASS DBGC_RPC_SRV
75
76 #ifndef MAX_OPEN_PRINTER_EXS
77 #define MAX_OPEN_PRINTER_EXS 50
78 #endif
79
80 #define GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT 5
81 #define GLOBAL_SPOOLSS_OS_MINOR_DEFAULT 2
82 #define GLOBAL_SPOOLSS_OS_BUILD_DEFAULT 3790
83 #define GLOBAL_SPOOLSS_ARCHITECTURE SPOOLSS_ARCHITECTURE_x64
84
85 static struct printer_handle *printers_list;
86
87 struct printer_session_counter {
88         struct printer_session_counter *next;
89         struct printer_session_counter *prev;
90
91         int snum;
92         uint32_t counter;
93 };
94
95 static struct printer_session_counter *counter_list;
96
97 struct notify_back_channel {
98         struct notify_back_channel *prev, *next;
99
100         /* associated client */
101         struct sockaddr_storage client_address;
102
103         /* print notify back-channel pipe handle*/
104         struct rpc_pipe_client *cli_pipe;
105         struct cli_state *cli;
106         uint32_t active_connections;
107 };
108
109 static struct notify_back_channel *back_channels;
110
111 /* Map generic permissions to printer object specific permissions */
112
113 const struct standard_mapping printer_std_mapping = {
114         PRINTER_READ,
115         PRINTER_WRITE,
116         PRINTER_EXECUTE,
117         PRINTER_ALL_ACCESS
118 };
119
120 /* Map generic permissions to print server object specific permissions */
121
122 const struct standard_mapping printserver_std_mapping = {
123         SERVER_READ,
124         SERVER_WRITE,
125         SERVER_EXECUTE,
126         SERVER_ALL_ACCESS
127 };
128
129 /* API table for Xcv Monitor functions */
130
131 struct xcv_api_table {
132         const char *name;
133         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
134 };
135
136 static void prune_printername_cache(void);
137
138 /********************************************************************
139  * Canonicalize servername.
140  ********************************************************************/
141
142 static const char *canon_servername(const char *servername)
143 {
144         const char *pservername = servername;
145         while (*pservername == '\\') {
146                 pservername++;
147         }
148         return pservername;
149 }
150
151 /* translate between internal status numbers and NT status numbers */
152 static int nt_printj_status(int v)
153 {
154         switch (v) {
155         case LPQ_QUEUED:
156                 return 0;
157         case LPQ_PAUSED:
158                 return JOB_STATUS_PAUSED;
159         case LPQ_SPOOLING:
160                 return JOB_STATUS_SPOOLING;
161         case LPQ_PRINTING:
162                 return JOB_STATUS_PRINTING;
163         case LPQ_ERROR:
164                 return JOB_STATUS_ERROR;
165         case LPQ_DELETING:
166                 return JOB_STATUS_DELETING;
167         case LPQ_OFFLINE:
168                 return JOB_STATUS_OFFLINE;
169         case LPQ_PAPEROUT:
170                 return JOB_STATUS_PAPEROUT;
171         case LPQ_PRINTED:
172                 return JOB_STATUS_PRINTED;
173         case LPQ_DELETED:
174                 return JOB_STATUS_DELETED;
175         case LPQ_BLOCKED:
176                 return JOB_STATUS_BLOCKED_DEVQ;
177         case LPQ_USER_INTERVENTION:
178                 return JOB_STATUS_USER_INTERVENTION;
179         }
180         return 0;
181 }
182
183 static int nt_printq_status(int v)
184 {
185         switch (v) {
186         case LPQ_PAUSED:
187                 return PRINTER_STATUS_PAUSED;
188         case LPQ_QUEUED:
189         case LPQ_SPOOLING:
190         case LPQ_PRINTING:
191                 return 0;
192         }
193         return 0;
194 }
195
196 /***************************************************************************
197  Disconnect from the client
198 ****************************************************************************/
199
200 static void srv_spoolss_replycloseprinter(int snum,
201                                           struct printer_handle *prn_hnd)
202 {
203         WERROR result;
204         NTSTATUS status;
205
206         /*
207          * Tell the specific printing tdb we no longer want messages for this printer
208          * by deregistering our PID.
209          */
210
211         if (!print_notify_deregister_pid(snum)) {
212                 DEBUG(0, ("Failed to register our pid for printer %s\n",
213                           lp_const_servicename(snum)));
214         }
215
216         /* weird if the test succeeds !!! */
217         if (prn_hnd->notify.cli_chan == NULL ||
218             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
219             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
220             prn_hnd->notify.cli_chan->active_connections == 0) {
221                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
222                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
223                 TALLOC_FREE(prn_hnd->notify.cli_chan);
224                 return;
225         }
226
227         status = dcerpc_spoolss_ReplyClosePrinter(
228                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
229                                         talloc_tos(),
230                                         &prn_hnd->notify.cli_hnd,
231                                         &result);
232         if (!NT_STATUS_IS_OK(status)) {
233                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
234                           nt_errstr(status)));
235                 result = ntstatus_to_werror(status);
236         } else if (!W_ERROR_IS_OK(result)) {
237                 DEBUG(0, ("reply_close_printer failed [%s].\n",
238                           win_errstr(result)));
239         }
240
241         /* if it's the last connection, deconnect the IPC$ share */
242         if (prn_hnd->notify.cli_chan->active_connections == 1) {
243
244                 cli_shutdown(prn_hnd->notify.cli_chan->cli);
245                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
246                 TALLOC_FREE(prn_hnd->notify.cli_chan);
247
248                 if (prn_hnd->notify.msg_ctx != NULL) {
249                         messaging_deregister(prn_hnd->notify.msg_ctx,
250                                              MSG_PRINTER_NOTIFY2, NULL);
251                 }
252         }
253
254         if (prn_hnd->notify.cli_chan) {
255                 prn_hnd->notify.cli_chan->active_connections--;
256                 prn_hnd->notify.cli_chan = NULL;
257         }
258 }
259
260 /****************************************************************************
261  Functions to free a printer entry datastruct.
262 ****************************************************************************/
263
264 static int printer_entry_destructor(struct printer_handle *Printer)
265 {
266         if (Printer->notify.cli_chan != NULL &&
267             Printer->notify.cli_chan->active_connections > 0) {
268                 int snum = -1;
269
270                 switch(Printer->printer_type) {
271                 case SPLHND_SERVER:
272                         srv_spoolss_replycloseprinter(snum, Printer);
273                         break;
274
275                 case SPLHND_PRINTER:
276                         snum = print_queue_snum(Printer->sharename);
277                         if (snum != -1) {
278                                 srv_spoolss_replycloseprinter(snum, Printer);
279                         }
280                         break;
281                 default:
282                         break;
283                 }
284         }
285
286         Printer->notify.flags=0;
287         Printer->notify.options=0;
288         Printer->notify.localmachine[0]='\0';
289         Printer->notify.printerlocal=0;
290         TALLOC_FREE(Printer->notify.option);
291         TALLOC_FREE(Printer->devmode);
292
293         /* Remove from the internal list. */
294         DLIST_REMOVE(printers_list, Printer);
295         return 0;
296 }
297
298 /****************************************************************************
299   find printer index by handle
300 ****************************************************************************/
301
302 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
303                                                         struct policy_handle *hnd)
304 {
305         struct printer_handle *find_printer = NULL;
306
307         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
308                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
309                 return NULL;
310         }
311
312         return find_printer;
313 }
314
315 /****************************************************************************
316  Close printer index by handle.
317 ****************************************************************************/
318
319 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
320 {
321         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
322
323         if (!Printer) {
324                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
325                         OUR_HANDLE(hnd)));
326                 return false;
327         }
328
329         close_policy_hnd(p, hnd);
330
331         return true;
332 }
333
334 /****************************************************************************
335  Delete a printer given a handle.
336 ****************************************************************************/
337
338 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
339                                   const char *sharename,
340                                   struct messaging_context *msg_ctx)
341 {
342         char *cmd = lp_deleteprinter_command(talloc_tos());
343         char *command = NULL;
344         int ret;
345         bool is_print_op = false;
346
347         /* can't fail if we don't try */
348
349         if ( !*cmd )
350                 return WERR_OK;
351
352         command = talloc_asprintf(ctx,
353                         "%s \"%s\"",
354                         cmd, sharename);
355         if (!command) {
356                 return WERR_NOT_ENOUGH_MEMORY;
357         }
358         if ( token )
359                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
360
361         DEBUG(10,("Running [%s]\n", command));
362
363         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
364
365         if ( is_print_op )
366                 become_root();
367
368         ret = smbrun(command, NULL, NULL);
369         if (ret == 0) {
370                 /* Tell everyone we updated smb.conf. */
371                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
372         }
373
374         if ( is_print_op )
375                 unbecome_root();
376
377         /********** END SePrintOperatorPrivlege BLOCK **********/
378
379         DEBUGADD(10,("returned [%d]\n", ret));
380
381         TALLOC_FREE(command);
382
383         if (ret != 0)
384                 return WERR_INVALID_HANDLE; /* What to return here? */
385
386         return WERR_OK;
387 }
388
389 /****************************************************************************
390  Delete a printer given a handle.
391 ****************************************************************************/
392
393 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
394 {
395         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
396         WERROR result;
397
398         if (!Printer) {
399                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
400                         OUR_HANDLE(hnd)));
401                 return WERR_INVALID_HANDLE;
402         }
403
404         /*
405          * It turns out that Windows allows delete printer on a handle
406          * opened by an admin user, then used on a pipe handle created
407          * by an anonymous user..... but they're working on security.... riiight !
408          * JRA.
409          */
410
411         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
412                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
413                 return WERR_ACCESS_DENIED;
414         }
415
416         /* this does not need a become root since the access check has been
417            done on the handle already */
418
419         result = winreg_delete_printer_key_internal(p->mem_ctx,
420                                            get_session_info_system(),
421                                            p->msg_ctx,
422                                            Printer->sharename,
423                                            "");
424         if (!W_ERROR_IS_OK(result)) {
425                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
426                 return WERR_INVALID_HANDLE;
427         }
428
429         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
430                                      Printer->sharename, p->msg_ctx);
431         if (!W_ERROR_IS_OK(result)) {
432                 return result;
433         }
434         prune_printername_cache();
435         return WERR_OK;
436 }
437
438 /****************************************************************************
439  Return the snum of a printer corresponding to an handle.
440 ****************************************************************************/
441
442 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
443                              int *number, struct share_params **params)
444 {
445         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
446
447         if (!Printer) {
448                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
449                         OUR_HANDLE(hnd)));
450                 return false;
451         }
452
453         switch (Printer->printer_type) {
454                 case SPLHND_PRINTER:
455                         DEBUG(4,("short name:%s\n", Printer->sharename));
456                         *number = print_queue_snum(Printer->sharename);
457                         return (*number != -1);
458                 case SPLHND_SERVER:
459                         return false;
460                 default:
461                         return false;
462         }
463 }
464
465 /****************************************************************************
466  Set printer handle type.
467  Check if it's \\server or \\server\printer
468 ****************************************************************************/
469
470 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
471 {
472         DEBUG(3,("Setting printer type=%s\n", handlename));
473
474         /* it's a print server */
475         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
476                 DEBUGADD(4,("Printer is a print server\n"));
477                 Printer->printer_type = SPLHND_SERVER;
478         }
479         /* it's a printer (set_printer_hnd_name() will handle port monitors */
480         else {
481                 DEBUGADD(4,("Printer is a printer\n"));
482                 Printer->printer_type = SPLHND_PRINTER;
483         }
484
485         return true;
486 }
487
488 static void prune_printername_cache_fn(const char *key, const char *value,
489                                        time_t timeout, void *private_data)
490 {
491         gencache_del(key);
492 }
493
494 static void prune_printername_cache(void)
495 {
496         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
497 }
498
499 /****************************************************************************
500  Set printer handle name..  Accept names like \\server, \\server\printer,
501  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
502  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
503  XcvDataPort() interface.
504 ****************************************************************************/
505
506 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
507                                    const struct auth_session_info *session_info,
508                                    struct messaging_context *msg_ctx,
509                                    struct printer_handle *Printer,
510                                    const char *handlename)
511 {
512         int snum;
513         int n_services=lp_numservices();
514         char *aprinter;
515         const char *printername;
516         const char *servername = NULL;
517         fstring sname;
518         bool found = false;
519         struct spoolss_PrinterInfo2 *info2 = NULL;
520         WERROR result;
521         char *p;
522
523         /*
524          * Hopefully nobody names his printers like this. Maybe \ or ,
525          * are illegal in printer names even?
526          */
527         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
528         char *cache_key;
529         char *tmp;
530
531         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
532                 (unsigned long)strlen(handlename)));
533
534         aprinter = discard_const_p(char, handlename);
535         if ( *handlename == '\\' ) {
536                 servername = canon_servername(handlename);
537                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
538                         *aprinter = '\0';
539                         aprinter++;
540                 }
541                 if (!is_myname_or_ipaddr(servername)) {
542                         return WERR_INVALID_PRINTER_NAME;
543                 }
544                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
545                 if (Printer->servername == NULL) {
546                         return WERR_NOT_ENOUGH_MEMORY;
547                 }
548         }
549
550         if (Printer->printer_type == SPLHND_SERVER) {
551                 return WERR_OK;
552         }
553
554         if (Printer->printer_type != SPLHND_PRINTER) {
555                 return WERR_INVALID_HANDLE;
556         }
557
558         DEBUGADD(5, ("searching for [%s]\n", aprinter));
559
560         p = strchr(aprinter, ',');
561         if (p != NULL) {
562                 char *p2 = p;
563                 p++;
564                 if (*p == ' ') {
565                         p++;
566                 }
567                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
568                         *p2 = '\0';
569                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
570                         *p2 = '\0';
571                 }
572         }
573
574         if (p) {
575                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
576         }
577
578         /* check for the Port Monitor Interface */
579         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
580                 Printer->printer_type = SPLHND_PORTMON_TCP;
581                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
582                 found = true;
583         }
584         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
585                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
586                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
587                 found = true;
588         }
589
590         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
591         if (cache_key == NULL) {
592                 return WERR_NOT_ENOUGH_MEMORY;
593         }
594
595         /*
596          * With hundreds of printers, the "for" loop iterating all
597          * shares can be quite expensive, as it is done on every
598          * OpenPrinter. The loop maps "aprinter" to "sname", the
599          * result of which we cache in gencache.
600          */
601         if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
602                 found = (strcmp(tmp, printer_not_found) != 0);
603                 if (!found) {
604                         DEBUG(4, ("Printer %s not found\n", aprinter));
605                         TALLOC_FREE(tmp);
606                         return WERR_INVALID_PRINTER_NAME;
607                 }
608                 fstrcpy(sname, tmp);
609                 TALLOC_FREE(tmp);
610         }
611
612         /* Search all sharenames first as this is easier than pulling
613            the printer_info_2 off of disk. Don't use find_service() since
614            that calls out to map_username() */
615
616         /* do another loop to look for printernames */
617         for (snum = 0; !found && snum < n_services; snum++) {
618                 const char *printer = lp_const_servicename(snum);
619
620                 /* no point going on if this is not a printer */
621                 if (!(lp_snum_ok(snum) && lp_printable(snum))) {
622                         continue;
623                 }
624
625                 /* ignore [printers] share */
626                 if (strequal(printer, "printers")) {
627                         continue;
628                 }
629
630                 fstrcpy(sname, printer);
631                 if (strequal(aprinter, printer)) {
632                         found = true;
633                         break;
634                 }
635
636                 /* no point looking up the printer object if
637                    we aren't allowing printername != sharename */
638                 if (lp_force_printername(snum)) {
639                         continue;
640                 }
641
642                 result = winreg_get_printer_internal(mem_ctx,
643                                             session_info,
644                                             msg_ctx,
645                                             sname,
646                                             &info2);
647                 if ( !W_ERROR_IS_OK(result) ) {
648                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
649                                  sname, win_errstr(result)));
650                         continue;
651                 }
652
653                 printername = strrchr(info2->printername, '\\');
654                 if (printername == NULL) {
655                         printername = info2->printername;
656                 } else {
657                         printername++;
658                 }
659
660                 if (strequal(printername, aprinter)) {
661                         found = true;
662                         break;
663                 }
664
665                 DEBUGADD(10, ("printername: %s\n", printername));
666
667                 TALLOC_FREE(info2);
668         }
669
670         if (!found) {
671                 gencache_set(cache_key, printer_not_found,
672                              time(NULL) + 300);
673                 TALLOC_FREE(cache_key);
674                 DEBUGADD(4,("Printer not found\n"));
675                 return WERR_INVALID_PRINTER_NAME;
676         }
677
678         gencache_set(cache_key, sname, time(NULL) + 300);
679         TALLOC_FREE(cache_key);
680
681         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
682
683         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
684
685         return WERR_OK;
686 }
687
688 /****************************************************************************
689  Find first available printer slot. creates a printer handle for you.
690  ****************************************************************************/
691
692 static WERROR open_printer_hnd(struct pipes_struct *p,
693                                struct policy_handle *hnd,
694                                const char *name,
695                                uint32_t access_granted)
696 {
697         struct printer_handle *new_printer;
698         WERROR result;
699
700         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
701
702         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
703         if (new_printer == NULL) {
704                 return WERR_NOT_ENOUGH_MEMORY;
705         }
706         talloc_set_destructor(new_printer, printer_entry_destructor);
707
708         /* This also steals the printer_handle on the policy_handle */
709         if (!create_policy_hnd(p, hnd, new_printer)) {
710                 TALLOC_FREE(new_printer);
711                 return WERR_INVALID_HANDLE;
712         }
713
714         /* Add to the internal list. */
715         DLIST_ADD(printers_list, new_printer);
716
717         new_printer->notify.option=NULL;
718
719         if (!set_printer_hnd_printertype(new_printer, name)) {
720                 close_printer_handle(p, hnd);
721                 return WERR_INVALID_HANDLE;
722         }
723
724         result = set_printer_hnd_name(p->mem_ctx,
725                                       get_session_info_system(),
726                                       p->msg_ctx,
727                                       new_printer, name);
728         if (!W_ERROR_IS_OK(result)) {
729                 close_printer_handle(p, hnd);
730                 return result;
731         }
732
733         new_printer->access_granted = access_granted;
734
735         DEBUG(5, ("%d printer handles active\n",
736                   (int)num_pipe_handles(p)));
737
738         return WERR_OK;
739 }
740
741 /***************************************************************************
742  check to see if the client motify handle is monitoring the notification
743  given by (notify_type, notify_field).
744  **************************************************************************/
745
746 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
747                                       uint16_t notify_field)
748 {
749         return true;
750 }
751
752 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
753                                 uint16_t notify_field)
754 {
755         struct spoolss_NotifyOption *option = p->notify.option;
756         uint32_t i, j;
757
758         /*
759          * Flags should always be zero when the change notify
760          * is registered by the client's spooler.  A user Win32 app
761          * might use the flags though instead of the NOTIFY_OPTION_INFO
762          * --jerry
763          */
764
765         if (!option) {
766                 return false;
767         }
768
769         if (p->notify.flags)
770                 return is_monitoring_event_flags(
771                         p->notify.flags, notify_type, notify_field);
772
773         for (i = 0; i < option->count; i++) {
774
775                 /* Check match for notify_type */
776
777                 if (option->types[i].type != notify_type)
778                         continue;
779
780                 /* Check match for field */
781
782                 for (j = 0; j < option->types[i].count; j++) {
783                         if (option->types[i].fields[j].field == notify_field) {
784                                 return true;
785                         }
786                 }
787         }
788
789         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
790                    p->servername, p->sharename, notify_type, notify_field));
791
792         return false;
793 }
794
795 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
796         _data->data.integer[0] = _integer; \
797         _data->data.integer[1] = 0;
798
799
800 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
801         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
802         if (!_data->data.string.string) {\
803                 _data->data.string.size = 0; \
804         } \
805         _data->data.string.size = strlen_m_term(_p) * 2;
806
807 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
808         _data->data.devmode.devmode = _devmode;
809
810 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
811                                    struct tm *t,
812                                    const char **pp,
813                                    uint32_t *plen)
814 {
815         struct spoolss_Time st;
816         uint32_t len = 16;
817         char *p;
818
819         if (!init_systemtime(&st, t)) {
820                 return;
821         }
822
823         p = talloc_array(mem_ctx, char, len);
824         if (!p) {
825                 return;
826         }
827
828         /*
829          * Systemtime must be linearized as a set of UINT16's.
830          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
831          */
832
833         SSVAL(p, 0, st.year);
834         SSVAL(p, 2, st.month);
835         SSVAL(p, 4, st.day_of_week);
836         SSVAL(p, 6, st.day);
837         SSVAL(p, 8, st.hour);
838         SSVAL(p, 10, st.minute);
839         SSVAL(p, 12, st.second);
840         SSVAL(p, 14, st.millisecond);
841
842         *pp = p;
843         *plen = len;
844 }
845
846 /* Convert a notification message to a struct spoolss_Notify */
847
848 static void notify_one_value(struct spoolss_notify_msg *msg,
849                              struct spoolss_Notify *data,
850                              TALLOC_CTX *mem_ctx)
851 {
852         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
853 }
854
855 static void notify_string(struct spoolss_notify_msg *msg,
856                           struct spoolss_Notify *data,
857                           TALLOC_CTX *mem_ctx)
858 {
859         /* The length of the message includes the trailing \0 */
860
861         data->data.string.size = msg->len * 2;
862         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
863         if (!data->data.string.string) {
864                 data->data.string.size = 0;
865                 return;
866         }
867 }
868
869 static void notify_system_time(struct spoolss_notify_msg *msg,
870                                struct spoolss_Notify *data,
871                                TALLOC_CTX *mem_ctx)
872 {
873         data->data.string.string = NULL;
874         data->data.string.size = 0;
875
876         if (msg->len != sizeof(time_t)) {
877                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
878                           msg->len));
879                 return;
880         }
881
882         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
883                                &data->data.string.string,
884                                &data->data.string.size);
885 }
886
887 struct notify2_message_table {
888         const char *name;
889         void (*fn)(struct spoolss_notify_msg *msg,
890                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
891 };
892
893 static struct notify2_message_table printer_notify_table[] = {
894         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
895         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
896         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
897         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
898         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
899         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
900         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
901         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
902         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
903         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
904         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
905         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
906         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
907         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
908         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
909         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
910         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
911         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
912         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
913 };
914
915 static struct notify2_message_table job_notify_table[] = {
916         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
917         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
918         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
919         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
920         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
921         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
922         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
923         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
924         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
925         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
926         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
927         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
928         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
929         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
930         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
931         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
932         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
933         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
934         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
935         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
936         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
937         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
938         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
939         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
940 };
941
942
943 /***********************************************************************
944  Allocate talloc context for container object
945  **********************************************************************/
946
947 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
948 {
949         if ( !ctr )
950                 return;
951
952         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
953
954         return;
955 }
956
957 /***********************************************************************
958  release all allocated memory and zero out structure
959  **********************************************************************/
960
961 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
962 {
963         if ( !ctr )
964                 return;
965
966         if ( ctr->ctx )
967                 talloc_destroy(ctr->ctx);
968
969         ZERO_STRUCTP(ctr);
970
971         return;
972 }
973
974 /***********************************************************************
975  **********************************************************************/
976
977 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
978 {
979         if ( !ctr )
980                 return NULL;
981
982         return ctr->ctx;
983 }
984
985 /***********************************************************************
986  **********************************************************************/
987
988 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
989 {
990         if ( !ctr || !ctr->msg_groups )
991                 return NULL;
992
993         if ( idx >= ctr->num_groups )
994                 return NULL;
995
996         return &ctr->msg_groups[idx];
997
998 }
999
1000 /***********************************************************************
1001  How many groups of change messages do we have ?
1002  **********************************************************************/
1003
1004 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1005 {
1006         if ( !ctr )
1007                 return 0;
1008
1009         return ctr->num_groups;
1010 }
1011
1012 /***********************************************************************
1013  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1014  **********************************************************************/
1015
1016 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1017 {
1018         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1019         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1020         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1021         int                             i, new_slot;
1022
1023         if ( !ctr || !msg )
1024                 return 0;
1025
1026         /* loop over all groups looking for a matching printer name */
1027
1028         for ( i=0; i<ctr->num_groups; i++ ) {
1029                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1030                         break;
1031         }
1032
1033         /* add a new group? */
1034
1035         if ( i == ctr->num_groups ) {
1036                 ctr->num_groups++;
1037
1038                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1039                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1040                         return 0;
1041                 }
1042                 ctr->msg_groups = groups;
1043
1044                 /* clear the new entry and set the printer name */
1045
1046                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1047                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1048         }
1049
1050         /* add the change messages; 'i' is the correct index now regardless */
1051
1052         msg_grp = &ctr->msg_groups[i];
1053
1054         msg_grp->num_msgs++;
1055
1056         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1057                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1058                 return 0;
1059         }
1060         msg_grp->msgs = msg_list;
1061
1062         new_slot = msg_grp->num_msgs-1;
1063         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1064
1065         /* need to allocate own copy of data */
1066
1067         if ( msg->len != 0 )
1068                 msg_grp->msgs[new_slot].notify.data = (char *)
1069                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1070
1071         return ctr->num_groups;
1072 }
1073
1074 static void construct_info_data(struct spoolss_Notify *info_data,
1075                                 enum spoolss_NotifyType type,
1076                                 uint16_t field, int id);
1077
1078 /***********************************************************************
1079  Send a change notication message on all handles which have a call
1080  back registered
1081  **********************************************************************/
1082
1083 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1084                                   struct printer_handle *prn_hnd,
1085                                   SPOOLSS_NOTIFY_MSG *messages,
1086                                   uint32_t num_msgs,
1087                                   struct spoolss_Notify **_notifies,
1088                                   int *_count)
1089 {
1090         struct spoolss_Notify *notifies;
1091         SPOOLSS_NOTIFY_MSG *msg;
1092         int count = 0;
1093         uint32_t id;
1094         int i;
1095
1096         notifies = talloc_zero_array(mem_ctx,
1097                                      struct spoolss_Notify, num_msgs);
1098         if (!notifies) {
1099                 return ENOMEM;
1100         }
1101
1102         for (i = 0; i < num_msgs; i++) {
1103
1104                 msg = &messages[i];
1105
1106                 /* Are we monitoring this event? */
1107
1108                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1109                         continue;
1110                 }
1111
1112                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1113                            "for printer [%s]\n",
1114                            msg->type, msg->field, prn_hnd->sharename));
1115
1116                 /*
1117                  * if the is a printer notification handle and not a job
1118                  * notification type, then set the id to 0.
1119                  * Otherwise just use what was specified in the message.
1120                  *
1121                  * When registering change notification on a print server
1122                  * handle we always need to send back the id (snum) matching
1123                  * the printer for which the change took place.
1124                  * For change notify registered on a printer handle,
1125                  * this does not matter and the id should be 0.
1126                  *
1127                  * --jerry
1128                  */
1129
1130                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1131                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1132                         id = 0;
1133                 } else {
1134                         id = msg->id;
1135                 }
1136
1137                 /* Convert unix jobid to smb jobid */
1138
1139                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1140                         id = sysjob_to_jobid(msg->id);
1141
1142                         if (id == -1) {
1143                                 DEBUG(3, ("no such unix jobid %d\n",
1144                                           msg->id));
1145                                 continue;
1146                         }
1147                 }
1148
1149                 construct_info_data(&notifies[count],
1150                                     msg->type, msg->field, id);
1151
1152                 switch(msg->type) {
1153                 case PRINTER_NOTIFY_TYPE:
1154                         if (printer_notify_table[msg->field].fn) {
1155                                 printer_notify_table[msg->field].fn(msg,
1156                                                 &notifies[count], mem_ctx);
1157                         }
1158                         break;
1159
1160                 case JOB_NOTIFY_TYPE:
1161                         if (job_notify_table[msg->field].fn) {
1162                                 job_notify_table[msg->field].fn(msg,
1163                                                 &notifies[count], mem_ctx);
1164                         }
1165                         break;
1166
1167                 default:
1168                         DEBUG(5, ("Unknown notification type %d\n",
1169                                   msg->type));
1170                         continue;
1171                 }
1172
1173                 count++;
1174         }
1175
1176         *_notifies = notifies;
1177         *_count = count;
1178
1179         return 0;
1180 }
1181
1182 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1183                                 struct printer_handle *prn_hnd,
1184                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1185 {
1186         struct spoolss_Notify *notifies;
1187         int count = 0;
1188         union spoolss_ReplyPrinterInfo info;
1189         struct spoolss_NotifyInfo info0;
1190         uint32_t reply_result;
1191         NTSTATUS status;
1192         WERROR werr;
1193         int ret;
1194
1195         /* Is there notification on this handle? */
1196         if (prn_hnd->notify.cli_chan == NULL ||
1197             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1198             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1199             prn_hnd->notify.cli_chan->active_connections == 0) {
1200                 return 0;
1201         }
1202
1203         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1204                    prn_hnd->servername, prn_hnd->sharename));
1205
1206         /* For this printer? Print servers always receive notifications. */
1207         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1208             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1209                 return 0;
1210         }
1211
1212         DEBUG(10,("Our printer\n"));
1213
1214         /* build the array of change notifications */
1215         ret = build_notify2_messages(mem_ctx, prn_hnd,
1216                                      msg_group->msgs,
1217                                      msg_group->num_msgs,
1218                                      &notifies, &count);
1219         if (ret) {
1220                 return ret;
1221         }
1222
1223         info0.version   = 0x2;
1224         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1225         info0.count     = count;
1226         info0.notifies  = notifies;
1227
1228         info.info0 = &info0;
1229
1230         status = dcerpc_spoolss_RouterReplyPrinterEx(
1231                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1232                                 mem_ctx,
1233                                 &prn_hnd->notify.cli_hnd,
1234                                 prn_hnd->notify.change, /* color */
1235                                 prn_hnd->notify.flags,
1236                                 &reply_result,
1237                                 0, /* reply_type, must be 0 */
1238                                 info, &werr);
1239         if (!NT_STATUS_IS_OK(status)) {
1240                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1241                           "failed: %s\n",
1242                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1243                           nt_errstr(status)));
1244                 werr = ntstatus_to_werror(status);
1245         } else if (!W_ERROR_IS_OK(werr)) {
1246                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1247                           "failed: %s\n",
1248                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1249                           win_errstr(werr)));
1250         }
1251         switch (reply_result) {
1252         case 0:
1253                 break;
1254         case PRINTER_NOTIFY_INFO_DISCARDED:
1255         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1256         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1257                 break;
1258         default:
1259                 break;
1260         }
1261
1262         return 0;
1263 }
1264
1265 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1266 {
1267         struct printer_handle    *p;
1268         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1269         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1270         int ret;
1271
1272         if ( !msg_group ) {
1273                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1274                 return;
1275         }
1276
1277         if (!msg_group->msgs) {
1278                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1279                 return;
1280         }
1281
1282         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1283
1284         /* loop over all printers */
1285
1286         for (p = printers_list; p; p = p->next) {
1287                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1288                 if (ret) {
1289                         goto done;
1290                 }
1291         }
1292
1293 done:
1294         DEBUG(8,("send_notify2_changes: Exit...\n"));
1295         return;
1296 }
1297
1298 /***********************************************************************
1299  **********************************************************************/
1300
1301 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1302 {
1303
1304         uint32_t tv_sec, tv_usec;
1305         size_t offset = 0;
1306
1307         /* Unpack message */
1308
1309         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1310                              msg->printer);
1311
1312         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1313                                 &tv_sec, &tv_usec,
1314                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1315
1316         if (msg->len == 0)
1317                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1318                            &msg->notify.value[0], &msg->notify.value[1]);
1319         else
1320                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1321                            &msg->len, &msg->notify.data);
1322
1323         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1324                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1325
1326         tv->tv_sec = tv_sec;
1327         tv->tv_usec = tv_usec;
1328
1329         if (msg->len == 0)
1330                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1331                           msg->notify.value[1]));
1332         else
1333                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1334
1335         return true;
1336 }
1337
1338 /********************************************************************
1339  Receive a notify2 message list
1340  ********************************************************************/
1341
1342 static void receive_notify2_message_list(struct messaging_context *msg,
1343                                          void *private_data,
1344                                          uint32_t msg_type,
1345                                          struct server_id server_id,
1346                                          DATA_BLOB *data)
1347 {
1348         size_t                  msg_count, i;
1349         char                    *buf = (char *)data->data;
1350         char                    *msg_ptr;
1351         size_t                  msg_len;
1352         SPOOLSS_NOTIFY_MSG      notify;
1353         SPOOLSS_NOTIFY_MSG_CTR  messages;
1354         int                     num_groups;
1355
1356         if (data->length < 4) {
1357                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1358                 return;
1359         }
1360
1361         msg_count = IVAL(buf, 0);
1362         msg_ptr = buf + 4;
1363
1364         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1365
1366         if (msg_count == 0) {
1367                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1368                 return;
1369         }
1370
1371         /* initialize the container */
1372
1373         ZERO_STRUCT( messages );
1374         notify_msg_ctr_init( &messages );
1375
1376         /*
1377          * build message groups for each printer identified
1378          * in a change_notify msg.  Remember that a PCN message
1379          * includes the handle returned for the srv_spoolss_replyopenprinter()
1380          * call.  Therefore messages are grouped according to printer handle.
1381          */
1382
1383         for ( i=0; i<msg_count; i++ ) {
1384                 struct timeval msg_tv;
1385
1386                 if (msg_ptr + 4 - buf > data->length) {
1387                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1388                         return;
1389                 }
1390
1391                 msg_len = IVAL(msg_ptr,0);
1392                 msg_ptr += 4;
1393
1394                 if (msg_ptr + msg_len - buf > data->length) {
1395                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1396                         return;
1397                 }
1398
1399                 /* unpack messages */
1400
1401                 ZERO_STRUCT( notify );
1402                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1403                 msg_ptr += msg_len;
1404
1405                 /* add to correct list in container */
1406
1407                 notify_msg_ctr_addmsg( &messages, &notify );
1408
1409                 /* free memory that might have been allocated by notify2_unpack_msg() */
1410
1411                 if ( notify.len != 0 )
1412                         SAFE_FREE( notify.notify.data );
1413         }
1414
1415         /* process each group of messages */
1416
1417         num_groups = notify_msg_ctr_numgroups( &messages );
1418         for ( i=0; i<num_groups; i++ )
1419                 send_notify2_changes( &messages, i );
1420
1421
1422         /* cleanup */
1423
1424         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1425                 (uint32_t)msg_count ));
1426
1427         notify_msg_ctr_destroy( &messages );
1428
1429         return;
1430 }
1431
1432 /********************************************************************
1433  Send a message to ourself about new driver being installed
1434  so we can upgrade the information for each printer bound to this
1435  driver
1436  ********************************************************************/
1437
1438 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1439                                             struct messaging_context *msg_ctx)
1440 {
1441         int len = strlen(drivername);
1442
1443         if (!len)
1444                 return false;
1445
1446         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1447                 drivername));
1448
1449         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1450                            MSG_PRINTER_DRVUPGRADE,
1451                            (const uint8_t *)drivername, len+1);
1452
1453         return true;
1454 }
1455
1456 void srv_spoolss_cleanup(void)
1457 {
1458         struct printer_session_counter *session_counter;
1459
1460         for (session_counter = counter_list;
1461              session_counter != NULL;
1462              session_counter = counter_list) {
1463                 DLIST_REMOVE(counter_list, session_counter);
1464                 TALLOC_FREE(session_counter);
1465         }
1466 }
1467
1468 /**********************************************************************
1469  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1470  over all printers, upgrading ones as necessary
1471  This is now *ONLY* called inside the background lpq updater. JRA.
1472  **********************************************************************/
1473
1474 void do_drv_upgrade_printer(struct messaging_context *msg,
1475                             void *private_data,
1476                             uint32_t msg_type,
1477                             struct server_id server_id,
1478                             DATA_BLOB *data)
1479 {
1480         TALLOC_CTX *tmp_ctx;
1481         const struct auth_session_info *session_info = get_session_info_system();
1482         struct spoolss_PrinterInfo2 *pinfo2;
1483         WERROR result;
1484         const char *drivername;
1485         int snum;
1486         int n_services = lp_numservices();
1487         struct dcerpc_binding_handle *b = NULL;
1488
1489         tmp_ctx = talloc_new(NULL);
1490         if (!tmp_ctx) return;
1491
1492         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1493         if (!drivername) {
1494                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1495                 goto done;
1496         }
1497
1498         DEBUG(10, ("do_drv_upgrade_printer: "
1499                    "Got message for new driver [%s]\n", drivername));
1500
1501         /* Iterate the printer list */
1502
1503         for (snum = 0; snum < n_services; snum++) {
1504                 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1505                         continue;
1506                 }
1507
1508                 /* ignore [printers] share */
1509                 if (strequal(lp_const_servicename(snum), "printers")) {
1510                         continue;
1511                 }
1512
1513                 if (b == NULL) {
1514                         result = winreg_printer_binding_handle(tmp_ctx,
1515                                                                session_info,
1516                                                                msg,
1517                                                                &b);
1518                         if (!W_ERROR_IS_OK(result)) {
1519                                 break;
1520                         }
1521                 }
1522
1523                 result = winreg_get_printer(tmp_ctx, b,
1524                                             lp_const_servicename(snum),
1525                                             &pinfo2);
1526
1527                 if (!W_ERROR_IS_OK(result)) {
1528                         continue;
1529                 }
1530
1531                 if (!pinfo2->drivername) {
1532                         continue;
1533                 }
1534
1535                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1536                         continue;
1537                 }
1538
1539                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1540
1541                 /* all we care about currently is the change_id */
1542                 result = winreg_printer_update_changeid(tmp_ctx, b,
1543                                                         pinfo2->printername);
1544
1545                 if (!W_ERROR_IS_OK(result)) {
1546                         DEBUG(3, ("do_drv_upgrade_printer: "
1547                                   "Failed to update changeid [%s]\n",
1548                                   win_errstr(result)));
1549                 }
1550         }
1551
1552         /* all done */
1553 done:
1554         talloc_free(tmp_ctx);
1555 }
1556
1557 /********************************************************************
1558  Update the cache for all printq's with a registered client
1559  connection
1560  ********************************************************************/
1561
1562 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1563 {
1564         struct printer_handle *printer = printers_list;
1565         int snum;
1566
1567         /* loop through all printers and update the cache where
1568            a client is connected */
1569         while (printer) {
1570                 if ((printer->printer_type == SPLHND_PRINTER) &&
1571                     ((printer->notify.cli_chan != NULL) &&
1572                      (printer->notify.cli_chan->active_connections > 0))) {
1573                         snum = print_queue_snum(printer->sharename);
1574                         print_queue_status(msg_ctx, snum, NULL, NULL);
1575                 }
1576
1577                 printer = printer->next;
1578         }
1579
1580         return;
1581 }
1582
1583 /****************************************************************
1584  _spoolss_OpenPrinter
1585 ****************************************************************/
1586
1587 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1588                             struct spoolss_OpenPrinter *r)
1589 {
1590         struct spoolss_OpenPrinterEx e;
1591         struct spoolss_UserLevel1 level1;
1592         WERROR werr;
1593
1594         ZERO_STRUCT(level1);
1595
1596         e.in.printername        = r->in.printername;
1597         e.in.datatype           = r->in.datatype;
1598         e.in.devmode_ctr        = r->in.devmode_ctr;
1599         e.in.access_mask        = r->in.access_mask;
1600         e.in.userlevel_ctr.level                = 1;
1601         e.in.userlevel_ctr.user_info.level1     = &level1;
1602
1603         e.out.handle            = r->out.handle;
1604
1605         werr = _spoolss_OpenPrinterEx(p, &e);
1606
1607         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
1608                 /* OpenPrinterEx returns this for a bad
1609                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1610                  * instead.
1611                  */
1612                 werr = WERR_INVALID_PRINTER_NAME;
1613         }
1614
1615         return werr;
1616 }
1617
1618 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1619                               struct spoolss_DeviceMode *orig,
1620                               struct spoolss_DeviceMode **dest)
1621 {
1622         struct spoolss_DeviceMode *dm;
1623
1624         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1625         if (!dm) {
1626                 return WERR_NOT_ENOUGH_MEMORY;
1627         }
1628
1629         /* copy all values, then duplicate strings and structs */
1630         *dm = *orig;
1631
1632         dm->devicename = talloc_strdup(dm, orig->devicename);
1633         if (!dm->devicename) {
1634                 return WERR_NOT_ENOUGH_MEMORY;
1635         }
1636         dm->formname = talloc_strdup(dm, orig->formname);
1637         if (!dm->formname) {
1638                 return WERR_NOT_ENOUGH_MEMORY;
1639         }
1640         if (orig->driverextra_data.data) {
1641                 dm->driverextra_data.data =
1642                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1643                                         orig->driverextra_data.length);
1644                 if (!dm->driverextra_data.data) {
1645                         return WERR_NOT_ENOUGH_MEMORY;
1646                 }
1647         }
1648
1649         *dest = dm;
1650         return WERR_OK;
1651 }
1652
1653 /****************************************************************
1654  _spoolss_OpenPrinterEx
1655 ****************************************************************/
1656
1657 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1658                               struct spoolss_OpenPrinterEx *r)
1659 {
1660         int snum;
1661         char *raddr;
1662         char *rhost;
1663         struct printer_handle *Printer=NULL;
1664         WERROR result;
1665         int rc;
1666
1667         if (!r->in.printername) {
1668                 return WERR_INVALID_PARAMETER;
1669         }
1670
1671         if (!*r->in.printername) {
1672                 return WERR_INVALID_PARAMETER;
1673         }
1674
1675         if (r->in.userlevel_ctr.level > 3) {
1676                 return WERR_INVALID_PARAMETER;
1677         }
1678         if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1679             (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1680             (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1681                 return WERR_INVALID_PARAMETER;
1682         }
1683
1684         /*
1685          * The printcap printer share inventory is updated on client
1686          * enumeration. For clients that do not perform enumeration prior to
1687          * access, such as cupssmbadd, we reinitialise the printer share
1688          * inventory on open as well.
1689          */
1690         become_root();
1691         delete_and_reload_printers(server_event_context(), p->msg_ctx);
1692         unbecome_root();
1693
1694         /* some sanity check because you can open a printer or a print server */
1695         /* aka: \\server\printer or \\server */
1696
1697         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1698
1699         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1700         if (!W_ERROR_IS_OK(result)) {
1701                 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1702                         "for printer %s\n", r->in.printername));
1703                 ZERO_STRUCTP(r->out.handle);
1704                 return result;
1705         }
1706
1707         Printer = find_printer_index_by_hnd(p, r->out.handle);
1708         if ( !Printer ) {
1709                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1710                         "handle we created for printer %s\n", r->in.printername));
1711                 close_printer_handle(p, r->out.handle);
1712                 ZERO_STRUCTP(r->out.handle);
1713                 return WERR_INVALID_PARAMETER;
1714         }
1715
1716         /*
1717          * First case: the user is opening the print server:
1718          *
1719          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1720          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1721          *
1722          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1723          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1724          * or if the user is listed in the smb.conf printer admin parameter.
1725          *
1726          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1727          * client view printer folder, but does not show the MSAPW.
1728          *
1729          * Note: this test needs code to check access rights here too. Jeremy
1730          * could you look at this?
1731          *
1732          * Second case: the user is opening a printer:
1733          * NT doesn't let us connect to a printer if the connecting user
1734          * doesn't have print permission.
1735          *
1736          * Third case: user is opening a Port Monitor
1737          * access checks same as opening a handle to the print server.
1738          */
1739
1740         switch (Printer->printer_type )
1741         {
1742         case SPLHND_SERVER:
1743         case SPLHND_PORTMON_TCP:
1744         case SPLHND_PORTMON_LOCAL:
1745                 /* Printserver handles use global struct... */
1746
1747                 snum = -1;
1748
1749                 if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
1750                         r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
1751                         r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
1752                 }
1753
1754                 /* Map standard access rights to object specific access rights */
1755
1756                 se_map_standard(&r->in.access_mask,
1757                                 &printserver_std_mapping);
1758
1759                 /* Deny any object specific bits that don't apply to print
1760                    servers (i.e printer and job specific bits) */
1761
1762                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1763
1764                 if (r->in.access_mask &
1765                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1766                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1767                         close_printer_handle(p, r->out.handle);
1768                         ZERO_STRUCTP(r->out.handle);
1769                         return WERR_ACCESS_DENIED;
1770                 }
1771
1772                 /* Allow admin access */
1773
1774                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1775                 {
1776                         if (!lp_show_add_printer_wizard()) {
1777                                 close_printer_handle(p, r->out.handle);
1778                                 ZERO_STRUCTP(r->out.handle);
1779                                 return WERR_ACCESS_DENIED;
1780                         }
1781
1782                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1783                            and not a printer admin, then fail */
1784
1785                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1786                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1787                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1788                                                 p->session_info->security_token)) {
1789                                 close_printer_handle(p, r->out.handle);
1790                                 ZERO_STRUCTP(r->out.handle);
1791                                 DEBUG(3,("access DENIED as user is not root, "
1792                                         "has no printoperator privilege and is "
1793                                         "not a member of the printoperator builtin group\n"));
1794                                 return WERR_ACCESS_DENIED;
1795                         }
1796
1797                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1798                 }
1799                 else
1800                 {
1801                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1802                 }
1803
1804                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1805                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1806
1807                 /* We fall through to return WERR_OK */
1808                 break;
1809
1810         case SPLHND_PRINTER:
1811                 /* NT doesn't let us connect to a printer if the connecting user
1812                    doesn't have print permission.  */
1813
1814                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1815                         close_printer_handle(p, r->out.handle);
1816                         ZERO_STRUCTP(r->out.handle);
1817                         return WERR_INVALID_HANDLE;
1818                 }
1819
1820                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1821                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1822                 }
1823
1824                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1825
1826                 /* map an empty access mask to the minimum access mask */
1827                 if (r->in.access_mask == 0x0)
1828                         r->in.access_mask = PRINTER_ACCESS_USE;
1829
1830                 /*
1831                  * If we are not serving the printer driver for this printer,
1832                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1833                  * will keep NT clients happy  --jerry
1834                  */
1835
1836                 if (lp_use_client_driver(snum)
1837                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1838                 {
1839                         r->in.access_mask = PRINTER_ACCESS_USE;
1840                 }
1841
1842                 /* check smb.conf parameters and the the sec_desc */
1843                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1844                                                          p->mem_ctx);
1845                 if (raddr == NULL) {
1846                         return WERR_NOT_ENOUGH_MEMORY;
1847                 }
1848
1849                 rc = get_remote_hostname(p->remote_address,
1850                                          &rhost,
1851                                          p->mem_ctx);
1852                 if (rc < 0) {
1853                         return WERR_NOT_ENOUGH_MEMORY;
1854                 }
1855                 if (strequal(rhost, "UNKNOWN")) {
1856                         rhost = raddr;
1857                 }
1858
1859                 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1860                                   rhost, raddr)) {
1861                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1862                         ZERO_STRUCTP(r->out.handle);
1863                         return WERR_ACCESS_DENIED;
1864                 }
1865
1866                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1867                                    p->session_info->security_token, snum) ||
1868                     !W_ERROR_IS_OK(print_access_check(p->session_info,
1869                                                       p->msg_ctx,
1870                                                       snum,
1871                                                       r->in.access_mask))) {
1872                         DEBUG(3, ("access DENIED for printer open\n"));
1873                         close_printer_handle(p, r->out.handle);
1874                         ZERO_STRUCTP(r->out.handle);
1875                         return WERR_ACCESS_DENIED;
1876                 }
1877
1878                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1879                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1880                         close_printer_handle(p, r->out.handle);
1881                         ZERO_STRUCTP(r->out.handle);
1882                         return WERR_ACCESS_DENIED;
1883                 }
1884
1885                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1886                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1887                 else
1888                         r->in.access_mask = PRINTER_ACCESS_USE;
1889
1890                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1891                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1892
1893                 winreg_create_printer_internal(p->mem_ctx,
1894                                       get_session_info_system(),
1895                                       p->msg_ctx,
1896                                       lp_const_servicename(snum));
1897
1898                 break;
1899
1900         default:
1901                 /* sanity check to prevent programmer error */
1902                 ZERO_STRUCTP(r->out.handle);
1903                 return WERR_INVALID_HANDLE;
1904         }
1905
1906         Printer->access_granted = r->in.access_mask;
1907
1908         /*
1909          * If the client sent a devmode in the OpenPrinter() call, then
1910          * save it here in case we get a job submission on this handle
1911          */
1912
1913          if ((Printer->printer_type != SPLHND_SERVER)
1914           && (r->in.devmode_ctr.devmode != NULL)) {
1915                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1916                                 &Printer->devmode);
1917          }
1918
1919         return WERR_OK;
1920 }
1921
1922 /****************************************************************
1923  _spoolss_ClosePrinter
1924 ****************************************************************/
1925
1926 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1927                              struct spoolss_ClosePrinter *r)
1928 {
1929         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1930
1931         if (Printer && Printer->document_started) {
1932                 struct spoolss_EndDocPrinter e;
1933
1934                 e.in.handle = r->in.handle;
1935
1936                 _spoolss_EndDocPrinter(p, &e);
1937         }
1938
1939         if (!close_printer_handle(p, r->in.handle))
1940                 return WERR_INVALID_HANDLE;
1941
1942         /* clear the returned printer handle.  Observed behavior
1943            from Win2k server.  Don't think this really matters.
1944            Previous code just copied the value of the closed
1945            handle.    --jerry */
1946
1947         ZERO_STRUCTP(r->out.handle);
1948
1949         return WERR_OK;
1950 }
1951
1952 /****************************************************************
1953  _spoolss_DeletePrinter
1954 ****************************************************************/
1955
1956 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1957                               struct spoolss_DeletePrinter *r)
1958 {
1959         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1960         WERROR result;
1961         int snum;
1962
1963         if (Printer && Printer->document_started) {
1964                 struct spoolss_EndDocPrinter e;
1965
1966                 e.in.handle = r->in.handle;
1967
1968                 _spoolss_EndDocPrinter(p, &e);
1969         }
1970
1971         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1972                 winreg_delete_printer_key_internal(p->mem_ctx,
1973                                           get_session_info_system(),
1974                                           p->msg_ctx,
1975                                           lp_const_servicename(snum),
1976                                           "");
1977         }
1978
1979         result = delete_printer_handle(p, r->in.handle);
1980
1981         return result;
1982 }
1983
1984 /*******************************************************************
1985  * static function to lookup the version id corresponding to an
1986  * long architecture string
1987  ******************************************************************/
1988
1989 static const struct print_architecture_table_node archi_table[]= {
1990
1991         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
1992         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
1993         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
1994         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
1995         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
1996         {"Windows IA64",         SPL_ARCH_IA64,         3 },
1997         {"Windows x64",          SPL_ARCH_X64,          3 },
1998         {NULL,                   "",            -1 }
1999 };
2000
2001 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2002                                    SPOOLSS_DRIVER_VERSION_NT35,
2003                                    SPOOLSS_DRIVER_VERSION_NT4,
2004                                    SPOOLSS_DRIVER_VERSION_200X,
2005                                    -1};
2006
2007 static int get_version_id(const char *arch)
2008 {
2009         int i;
2010
2011         for (i=0; archi_table[i].long_archi != NULL; i++)
2012         {
2013                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2014                         return (archi_table[i].version);
2015         }
2016
2017         return -1;
2018 }
2019
2020 /****************************************************************
2021  _spoolss_DeletePrinterDriver
2022 ****************************************************************/
2023
2024 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2025                                     struct spoolss_DeletePrinterDriver *r)
2026 {
2027
2028         struct spoolss_DriverInfo8 *info = NULL;
2029         int                             version;
2030         WERROR                          status;
2031         struct dcerpc_binding_handle *b;
2032         TALLOC_CTX *tmp_ctx = NULL;
2033         int i;
2034         bool found;
2035
2036         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2037            and not a printer admin, then fail */
2038
2039         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2040             !security_token_has_privilege(p->session_info->security_token,
2041                                           SEC_PRIV_PRINT_OPERATOR)) {
2042                 return WERR_ACCESS_DENIED;
2043         }
2044
2045         /* check that we have a valid driver name first */
2046
2047         if ((version = get_version_id(r->in.architecture)) == -1) {
2048                 return WERR_INVALID_ENVIRONMENT;
2049         }
2050
2051         tmp_ctx = talloc_new(p->mem_ctx);
2052         if (!tmp_ctx) {
2053                 return WERR_NOT_ENOUGH_MEMORY;
2054         }
2055
2056         status = winreg_printer_binding_handle(tmp_ctx,
2057                                                get_session_info_system(),
2058                                                p->msg_ctx,
2059                                                &b);
2060         if (!W_ERROR_IS_OK(status)) {
2061                 goto done;
2062         }
2063
2064         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2065                 status = winreg_get_driver(tmp_ctx, b,
2066                                            r->in.architecture, r->in.driver,
2067                                            drv_cversion[i], &info);
2068                 if (!W_ERROR_IS_OK(status)) {
2069                         DEBUG(5, ("skipping del of driver with version %d\n",
2070                                   drv_cversion[i]));
2071                         continue;
2072                 }
2073                 found = true;
2074
2075                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2076                         status = WERR_PRINTER_DRIVER_IN_USE;
2077                         goto done;
2078                 }
2079
2080                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2081                 if (!W_ERROR_IS_OK(status)) {
2082                         DEBUG(0, ("failed del of driver with version %d\n",
2083                                   drv_cversion[i]));
2084                         goto done;
2085                 }
2086         }
2087         if (found == false) {
2088                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2089                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2090         } else {
2091                 status = WERR_OK;
2092         }
2093
2094 done:
2095         talloc_free(tmp_ctx);
2096
2097         return status;
2098 }
2099
2100 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2101                                   struct pipes_struct *p,
2102                                   struct spoolss_DeletePrinterDriverEx *r,
2103                                   struct dcerpc_binding_handle *b,
2104                                   struct spoolss_DriverInfo8 *info)
2105 {
2106         WERROR status;
2107         bool delete_files;
2108
2109         if (printer_driver_in_use(mem_ctx, b, info)) {
2110                 status = WERR_PRINTER_DRIVER_IN_USE;
2111                 goto done;
2112         }
2113
2114         /*
2115          * we have a couple of cases to consider.
2116          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2117          *     then the delete should fail if **any** files overlap with
2118          *     other drivers
2119          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2120          *     non-overlapping files
2121          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2122          *     are set, then do not delete any files
2123          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2124          */
2125
2126         delete_files = r->in.delete_flags
2127                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2128
2129
2130         if (delete_files) {
2131                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2132                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2133                         status = WERR_PRINTER_DRIVER_IN_USE;
2134                         goto done;
2135                 }
2136                 /*
2137                  * printer_driver_files_in_use() has trimmed overlapping files
2138                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2139                  */
2140         }
2141
2142
2143         status = winreg_del_driver(mem_ctx, b, info, info->version);
2144         if (!W_ERROR_IS_OK(status)) {
2145                 goto done;
2146         }
2147
2148         /*
2149          * now delete any associated files if delete_files is
2150          * true. Even if this part failes, we return succes
2151          * because the driver doesn not exist any more
2152          */
2153         if (delete_files) {
2154                 delete_driver_files(p->session_info, info);
2155         }
2156
2157 done:
2158         return status;
2159 }
2160
2161 /****************************************************************
2162  _spoolss_DeletePrinterDriverEx
2163 ****************************************************************/
2164
2165 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2166                                       struct spoolss_DeletePrinterDriverEx *r)
2167 {
2168         struct spoolss_DriverInfo8 *info = NULL;
2169         WERROR                          status;
2170         struct dcerpc_binding_handle *b;
2171         TALLOC_CTX *tmp_ctx = NULL;
2172         int i;
2173         bool found;
2174
2175         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2176            and not a printer admin, then fail */
2177
2178         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2179             !security_token_has_privilege(p->session_info->security_token,
2180                                           SEC_PRIV_PRINT_OPERATOR)) {
2181                 return WERR_ACCESS_DENIED;
2182         }
2183
2184         /* check that we have a valid driver name first */
2185         if (get_version_id(r->in.architecture) == -1) {
2186                 /* this is what NT returns */
2187                 return WERR_INVALID_ENVIRONMENT;
2188         }
2189
2190         tmp_ctx = talloc_new(p->mem_ctx);
2191         if (!tmp_ctx) {
2192                 return WERR_NOT_ENOUGH_MEMORY;
2193         }
2194
2195         status = winreg_printer_binding_handle(tmp_ctx,
2196                                                get_session_info_system(),
2197                                                p->msg_ctx,
2198                                                &b);
2199         if (!W_ERROR_IS_OK(status)) {
2200                 goto done;
2201         }
2202
2203         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2204                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2205                  && (drv_cversion[i] != r->in.version)) {
2206                         continue;
2207                 }
2208
2209                 /* check if a driver with this version exists before delete */
2210                 status = winreg_get_driver(tmp_ctx, b,
2211                                            r->in.architecture, r->in.driver,
2212                                            drv_cversion[i], &info);
2213                 if (!W_ERROR_IS_OK(status)) {
2214                         DEBUG(5, ("skipping del of driver with version %d\n",
2215                                   drv_cversion[i]));
2216                         continue;
2217                 }
2218                 found = true;
2219
2220                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2221                 if (!W_ERROR_IS_OK(status)) {
2222                         DEBUG(0, ("failed to delete driver with version %d\n",
2223                                   drv_cversion[i]));
2224                         goto done;
2225                 }
2226         }
2227         if (found == false) {
2228                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2229                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2230         } else {
2231                 status = WERR_OK;
2232         }
2233
2234 done:
2235         talloc_free(tmp_ctx);
2236         return status;
2237 }
2238
2239
2240 /********************************************************************
2241  GetPrinterData on a printer server Handle.
2242 ********************************************************************/
2243
2244 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2245                                             const char *value,
2246                                             enum winreg_Type *type,
2247                                             union spoolss_PrinterData *data)
2248 {
2249         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2250
2251         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2252                 *type = REG_DWORD;
2253                 SIVAL(&data->value, 0, 0x00);
2254                 return WERR_OK;
2255         }
2256
2257         if (!strcasecmp_m(value, "BeepEnabled")) {
2258                 *type = REG_DWORD;
2259                 SIVAL(&data->value, 0, 0x00);
2260                 return WERR_OK;
2261         }
2262
2263         if (!strcasecmp_m(value, "EventLog")) {
2264                 *type = REG_DWORD;
2265                 /* formally was 0x1b */
2266                 SIVAL(&data->value, 0, 0x00);
2267                 return WERR_OK;
2268         }
2269
2270         if (!strcasecmp_m(value, "NetPopup")) {
2271                 *type = REG_DWORD;
2272                 SIVAL(&data->value, 0, 0x00);
2273                 return WERR_OK;
2274         }
2275
2276         if (!strcasecmp_m(value, "MajorVersion")) {
2277                 *type = REG_DWORD;
2278
2279                 /* Windows NT 4.0 seems to not allow uploading of drivers
2280                    to a server that reports 0x3 as the MajorVersion.
2281                    need to investigate more how Win2k gets around this .
2282                    -- jerry */
2283
2284                 if (RA_WINNT == get_remote_arch()) {
2285                         SIVAL(&data->value, 0, 0x02);
2286                 } else {
2287                         SIVAL(&data->value, 0, 0x03);
2288                 }
2289
2290                 return WERR_OK;
2291         }
2292
2293         if (!strcasecmp_m(value, "MinorVersion")) {
2294                 *type = REG_DWORD;
2295                 SIVAL(&data->value, 0, 0x00);
2296                 return WERR_OK;
2297         }
2298
2299         /* REG_BINARY
2300          *  uint32_t size        = 0x114
2301          *  uint32_t major       = 5
2302          *  uint32_t minor       = [0|1]
2303          *  uint32_t build       = [2195|2600]
2304          *  extra unicode string = e.g. "Service Pack 3"
2305          */
2306         if (!strcasecmp_m(value, "OSVersion")) {
2307                 DATA_BLOB blob;
2308                 enum ndr_err_code ndr_err;
2309                 struct spoolss_OSVersion os;
2310
2311                 /*
2312                  * Set the default OSVersion to:
2313                  *
2314                  *     Windows Server 2003R2 SP2 (5.2.3790)
2315                  *
2316                  * used to be Windows 2000 (5.0.2195)
2317                  */
2318                 os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
2319                                                       "spoolss", "os_major",
2320                                                       GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
2321                 os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
2322                                                       "spoolss", "os_minor",
2323                                                       GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
2324                 os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
2325                                                       "spoolss", "os_build",
2326                                                       GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
2327                 os.extra_string         = "";   /* leave extra string empty */
2328
2329                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2330                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2331                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2332                         return WERR_GEN_FAILURE;
2333                 }
2334
2335                 if (DEBUGLEVEL >= 10) {
2336                         NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2337                 }
2338
2339                 *type = REG_BINARY;
2340                 data->binary = blob;
2341
2342                 return WERR_OK;
2343         }
2344
2345
2346         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2347                 *type = REG_SZ;
2348
2349                 data->string = talloc_strdup(mem_ctx, SPOOLSS_DEFAULT_SERVER_PATH);
2350                 W_ERROR_HAVE_NO_MEMORY(data->string);
2351
2352                 return WERR_OK;
2353         }
2354
2355         if (!strcasecmp_m(value, "Architecture")) {
2356                 *type = REG_SZ;
2357                 data->string = talloc_strdup(mem_ctx,
2358                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", GLOBAL_SPOOLSS_ARCHITECTURE));
2359                 W_ERROR_HAVE_NO_MEMORY(data->string);
2360
2361                 return WERR_OK;
2362         }
2363
2364         if (!strcasecmp_m(value, "DsPresent")) {
2365                 *type = REG_DWORD;
2366
2367                 /* only show the publish check box if we are a
2368                    member of a AD domain */
2369
2370                 if (lp_security() == SEC_ADS) {
2371                         SIVAL(&data->value, 0, 0x01);
2372                 } else {
2373                         SIVAL(&data->value, 0, 0x00);
2374                 }
2375                 return WERR_OK;
2376         }
2377
2378         if (!strcasecmp_m(value, "DNSMachineName")) {
2379                 const char *hostname = get_mydnsfullname();
2380
2381                 if (!hostname) {
2382                         return WERR_FILE_NOT_FOUND;
2383                 }
2384
2385                 *type = REG_SZ;
2386                 data->string = talloc_strdup(mem_ctx, hostname);
2387                 W_ERROR_HAVE_NO_MEMORY(data->string);
2388
2389                 return WERR_OK;
2390         }
2391
2392         *type = REG_NONE;
2393
2394         return WERR_INVALID_PARAMETER;
2395 }
2396
2397 /****************************************************************
2398  _spoolss_GetPrinterData
2399 ****************************************************************/
2400
2401 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2402                                struct spoolss_GetPrinterData *r)
2403 {
2404         struct spoolss_GetPrinterDataEx r2;
2405
2406         r2.in.handle            = r->in.handle;
2407         r2.in.key_name          = "PrinterDriverData";
2408         r2.in.value_name        = r->in.value_name;
2409         r2.in.offered           = r->in.offered;
2410         r2.out.type             = r->out.type;
2411         r2.out.data             = r->out.data;
2412         r2.out.needed           = r->out.needed;
2413
2414         return _spoolss_GetPrinterDataEx(p, &r2);
2415 }
2416
2417 /*********************************************************
2418  Connect to the client machine.
2419 **********************************************************/
2420
2421 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2422                                       struct sockaddr_storage *client_ss, const char *remote_machine)
2423 {
2424         NTSTATUS ret;
2425         struct sockaddr_storage rm_addr;
2426         char addr[INET6_ADDRSTRLEN];
2427
2428         if ( is_zero_addr(client_ss) ) {
2429                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2430                         remote_machine));
2431                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2432                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2433                         return false;
2434                 }
2435                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2436         } else {
2437                 rm_addr = *client_ss;
2438                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2439                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2440                         addr));
2441         }
2442
2443         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2444                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2445                         addr));
2446                 return false;
2447         }
2448
2449         /* setup the connection */
2450         ret = cli_full_connection( pp_cli, lp_netbios_name(), remote_machine,
2451                 &rm_addr, 0, "IPC$", "IPC",
2452                 "", /* username */
2453                 "", /* domain */
2454                 "", /* password */
2455                 0, lp_client_signing());
2456
2457         if ( !NT_STATUS_IS_OK( ret ) ) {
2458                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2459                         remote_machine ));
2460                 return false;
2461         }
2462
2463         if ( smbXcli_conn_protocol((*pp_cli)->conn) != PROTOCOL_NT1 ) {
2464                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2465                 cli_shutdown(*pp_cli);
2466                 return false;
2467         }
2468
2469         /*
2470          * Ok - we have an anonymous connection to the IPC$ share.
2471          * Now start the NT Domain stuff :-).
2472          */
2473
2474         ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2475         if (!NT_STATUS_IS_OK(ret)) {
2476                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2477                         remote_machine, nt_errstr(ret)));
2478                 cli_shutdown(*pp_cli);
2479                 return false;
2480         }
2481
2482         return true;
2483 }
2484
2485 /***************************************************************************
2486  Connect to the client.
2487 ****************************************************************************/
2488
2489 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2490                                         uint32_t localprinter,
2491                                         enum winreg_Type type,
2492                                         struct policy_handle *handle,
2493                                         struct notify_back_channel **_chan,
2494                                         struct sockaddr_storage *client_ss,
2495                                         struct messaging_context *msg_ctx)
2496 {
2497         WERROR result;
2498         NTSTATUS status;
2499         struct notify_back_channel *chan;
2500
2501         for (chan = back_channels; chan; chan = chan->next) {
2502                 if (memcmp(&chan->client_address, client_ss,
2503                            sizeof(struct sockaddr_storage)) == 0) {
2504                         break;
2505                 }
2506         }
2507
2508         /*
2509          * If it's the first connection, contact the client
2510          * and connect to the IPC$ share anonymously
2511          */
2512         if (!chan) {
2513                 fstring unix_printer;
2514
2515                 /* the +2 is to strip the leading 2 backslashs */
2516                 fstrcpy(unix_printer, printer + 2);
2517
2518                 chan = talloc_zero(NULL, struct notify_back_channel);
2519                 if (!chan) {
2520                         return false;
2521                 }
2522                 chan->client_address = *client_ss;
2523
2524                 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2525                         TALLOC_FREE(chan);
2526                         return false;
2527                 }
2528
2529                 DLIST_ADD(back_channels, chan);
2530
2531                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2532                                    receive_notify2_message_list);
2533         }
2534
2535         if (chan->cli_pipe == NULL ||
2536             chan->cli_pipe->binding_handle == NULL) {
2537                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2538                         "NULL %s for printer %s\n",
2539                         chan->cli_pipe == NULL ?
2540                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2541                         printer));
2542                 return false;
2543         }
2544
2545         /*
2546          * Tell the specific printing tdb we want messages for this printer
2547          * by registering our PID.
2548          */
2549
2550         if (!print_notify_register_pid(snum)) {
2551                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2552                           printer));
2553         }
2554
2555         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2556                                                  talloc_tos(),
2557                                                  printer,
2558                                                  localprinter,
2559                                                  type,
2560                                                  0,
2561                                                  NULL,
2562                                                  handle,
2563                                                  &result);
2564         if (!NT_STATUS_IS_OK(status)) {
2565                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2566                 result = ntstatus_to_werror(status);
2567         } else if (!W_ERROR_IS_OK(result)) {
2568                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2569         }
2570
2571         chan->active_connections++;
2572         *_chan = chan;
2573
2574         return (W_ERROR_IS_OK(result));
2575 }
2576
2577 /****************************************************************
2578  ****************************************************************/
2579
2580 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2581                                                              const struct spoolss_NotifyOption *r)
2582 {
2583         struct spoolss_NotifyOption *option;
2584         uint32_t i,k;
2585
2586         if (!r) {
2587                 return NULL;
2588         }
2589
2590         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2591         if (!option) {
2592                 return NULL;
2593         }
2594
2595         *option = *r;
2596
2597         if (!option->count) {
2598                 return option;
2599         }
2600
2601         option->types = talloc_zero_array(option,
2602                 struct spoolss_NotifyOptionType, option->count);
2603         if (!option->types) {
2604                 talloc_free(option);
2605                 return NULL;
2606         }
2607
2608         for (i=0; i < option->count; i++) {
2609                 option->types[i] = r->types[i];
2610
2611                 if (option->types[i].count) {
2612                         option->types[i].fields = talloc_zero_array(option,
2613                                 union spoolss_Field, option->types[i].count);
2614                         if (!option->types[i].fields) {
2615                                 talloc_free(option);
2616                                 return NULL;
2617                         }
2618                         for (k=0; k<option->types[i].count; k++) {
2619                                 option->types[i].fields[k] =
2620                                         r->types[i].fields[k];
2621                         }
2622                 }
2623         }
2624
2625         return option;
2626 }
2627
2628 /****************************************************************
2629  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2630  *
2631  * before replying OK: status=0 a rpc call is made to the workstation
2632  * asking ReplyOpenPrinter
2633  *
2634  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2635  * called from api_spoolss_rffpcnex
2636 ****************************************************************/
2637
2638 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2639                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2640 {
2641         int snum = -1;
2642         struct spoolss_NotifyOption *option = r->in.notify_options;
2643         struct sockaddr_storage client_ss;
2644         ssize_t client_len;
2645
2646         /* store the notify value in the printer struct */
2647
2648         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2649
2650         if (!Printer) {
2651                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2652                         "Invalid handle (%s:%u:%u).\n",
2653                         OUR_HANDLE(r->in.handle)));
2654                 return WERR_INVALID_HANDLE;
2655         }
2656
2657         Printer->notify.flags           = r->in.flags;
2658         Printer->notify.options         = r->in.options;
2659         Printer->notify.printerlocal    = r->in.printer_local;
2660         Printer->notify.msg_ctx         = p->msg_ctx;
2661
2662         TALLOC_FREE(Printer->notify.option);
2663         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2664
2665         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2666
2667         /* Connect to the client machine and send a ReplyOpenPrinter */
2668
2669         if ( Printer->printer_type == SPLHND_SERVER)
2670                 snum = -1;
2671         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2672                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2673                 return WERR_INVALID_HANDLE;
2674
2675         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2676                   "remote_address is %s\n",
2677                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2678
2679         if (!lp_print_notify_backchannel(snum)) {
2680                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2681                         "backchannel disabled\n"));
2682                 return WERR_RPC_S_SERVER_UNAVAILABLE;
2683         }
2684
2685         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2686                                                   (struct sockaddr *) &client_ss,
2687                                                   sizeof(struct sockaddr_storage));
2688         if (client_len < 0) {
2689                 return WERR_NOT_ENOUGH_MEMORY;
2690         }
2691
2692         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2693                                         Printer->notify.printerlocal, REG_SZ,
2694                                         &Printer->notify.cli_hnd,
2695                                         &Printer->notify.cli_chan,
2696                                         &client_ss, p->msg_ctx)) {
2697                 return WERR_RPC_S_SERVER_UNAVAILABLE;
2698         }
2699
2700         return WERR_OK;
2701 }
2702
2703 /*******************************************************************
2704  * fill a notify_info_data with the servername
2705  ********************************************************************/
2706
2707 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2708                                        int snum,
2709                                        struct spoolss_Notify *data,
2710                                        print_queue_struct *queue,
2711                                        struct spoolss_PrinterInfo2 *pinfo2,
2712                                        TALLOC_CTX *mem_ctx)
2713 {
2714         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2715 }
2716
2717 /*******************************************************************
2718  * fill a notify_info_data with the printername (not including the servername).
2719  ********************************************************************/
2720
2721 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2722                                         int snum,
2723                                         struct spoolss_Notify *data,
2724                                         print_queue_struct *queue,
2725                                         struct spoolss_PrinterInfo2 *pinfo2,
2726                                         TALLOC_CTX *mem_ctx)
2727 {
2728         /* the notify name should not contain the \\server\ part */
2729         const char *p = strrchr(pinfo2->printername, '\\');
2730
2731         if (!p) {
2732                 p = pinfo2->printername;
2733         } else {
2734                 p++;
2735         }
2736
2737         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2738 }
2739
2740 /*******************************************************************
2741  * fill a notify_info_data with the servicename
2742  ********************************************************************/
2743
2744 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2745                                       int snum,
2746                                       struct spoolss_Notify *data,
2747                                       print_queue_struct *queue,
2748                                       struct spoolss_PrinterInfo2 *pinfo2,
2749                                       TALLOC_CTX *mem_ctx)
2750 {
2751         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2752 }
2753
2754 /*******************************************************************
2755  * fill a notify_info_data with the port name
2756  ********************************************************************/
2757
2758 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2759                                      int snum,
2760                                      struct spoolss_Notify *data,
2761                                      print_queue_struct *queue,
2762                                      struct spoolss_PrinterInfo2 *pinfo2,
2763                                      TALLOC_CTX *mem_ctx)
2764 {
2765         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2766 }
2767
2768 /*******************************************************************
2769  * fill a notify_info_data with the printername
2770  * but it doesn't exist, have to see what to do
2771  ********************************************************************/
2772
2773 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2774                                        int snum,
2775                                        struct spoolss_Notify *data,
2776                                        print_queue_struct *queue,
2777                                        struct spoolss_PrinterInfo2 *pinfo2,
2778                                        TALLOC_CTX *mem_ctx)
2779 {
2780         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2781 }
2782
2783 /*******************************************************************
2784  * fill a notify_info_data with the comment
2785  ********************************************************************/
2786
2787 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2788                                    int snum,
2789                                    struct spoolss_Notify *data,
2790                                    print_queue_struct *queue,
2791                                    struct spoolss_PrinterInfo2 *pinfo2,
2792                                    TALLOC_CTX *mem_ctx)
2793 {
2794         const char *p;
2795
2796         if (*pinfo2->comment == '\0') {
2797                 p = lp_comment(talloc_tos(), snum);
2798         } else {
2799                 p = pinfo2->comment;
2800         }
2801
2802         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2803 }
2804
2805 /*******************************************************************
2806  * fill a notify_info_data with the comment
2807  * location = "Room 1, floor 2, building 3"
2808  ********************************************************************/
2809
2810 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2811                                     int snum,
2812                                     struct spoolss_Notify *data,
2813                                     print_queue_struct *queue,
2814                                     struct spoolss_PrinterInfo2 *pinfo2,
2815                                     TALLOC_CTX *mem_ctx)
2816 {
2817         const char *loc = pinfo2->location;
2818         NTSTATUS status;
2819
2820         status = printer_list_get_printer(mem_ctx,
2821                                           pinfo2->sharename,
2822                                           NULL,
2823                                           &loc,
2824                                           NULL);
2825         if (NT_STATUS_IS_OK(status)) {
2826                 if (loc == NULL) {
2827                         loc = pinfo2->location;
2828                 }
2829         }
2830
2831         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2832 }
2833
2834 /*******************************************************************
2835  * fill a notify_info_data with the device mode
2836  * jfm:xxxx don't to it for know but that's a real problem !!!
2837  ********************************************************************/
2838
2839 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2840                                    int snum,
2841                                    struct spoolss_Notify *data,
2842                                    print_queue_struct *queue,
2843                                    struct spoolss_PrinterInfo2 *pinfo2,
2844                                    TALLOC_CTX *mem_ctx)
2845 {
2846         /* for a dummy implementation we have to zero the fields */
2847         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2848 }
2849
2850 /*******************************************************************
2851  * fill a notify_info_data with the separator file name
2852  ********************************************************************/
2853
2854 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2855                                    int snum,
2856                                    struct spoolss_Notify *data,
2857                                    print_queue_struct *queue,
2858                                    struct spoolss_PrinterInfo2 *pinfo2,
2859                                    TALLOC_CTX *mem_ctx)
2860 {
2861         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2862 }
2863
2864 /*******************************************************************
2865  * fill a notify_info_data with the print processor
2866  * jfm:xxxx return always winprint to indicate we don't do anything to it
2867  ********************************************************************/
2868
2869 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2870                                            int snum,
2871                                            struct spoolss_Notify *data,
2872                                            print_queue_struct *queue,
2873                                            struct spoolss_PrinterInfo2 *pinfo2,
2874                                            TALLOC_CTX *mem_ctx)
2875 {
2876         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2877 }
2878
2879 /*******************************************************************
2880  * fill a notify_info_data with the print processor options
2881  * jfm:xxxx send an empty string
2882  ********************************************************************/
2883
2884 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2885                                       int snum,
2886                                       struct spoolss_Notify *data,
2887                                       print_queue_struct *queue,
2888                                       struct spoolss_PrinterInfo2 *pinfo2,
2889                                       TALLOC_CTX *mem_ctx)
2890 {
2891         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2892 }
2893
2894 /*******************************************************************
2895  * fill a notify_info_data with the data type
2896  * jfm:xxxx always send RAW as data type
2897  ********************************************************************/
2898
2899 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2900                                     int snum,
2901                                     struct spoolss_Notify *data,
2902                                     print_queue_struct *queue,
2903                                     struct spoolss_PrinterInfo2 *pinfo2,
2904                                     TALLOC_CTX *mem_ctx)
2905 {
2906         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2907 }
2908
2909 /*******************************************************************
2910  * fill a notify_info_data with the security descriptor
2911  * jfm:xxxx send an null pointer to say no security desc
2912  * have to implement security before !
2913  ********************************************************************/
2914
2915 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2916                                          int snum,
2917                                          struct spoolss_Notify *data,
2918                                          print_queue_struct *queue,
2919                                          struct spoolss_PrinterInfo2 *pinfo2,
2920                                          TALLOC_CTX *mem_ctx)
2921 {
2922         if (pinfo2->secdesc == NULL) {
2923                 data->data.sd.sd = NULL;
2924         } else {
2925                 data->data.sd.sd = security_descriptor_copy(mem_ctx,
2926                                                             pinfo2->secdesc);
2927         }
2928         data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2929                                                              0);
2930 }
2931
2932 /*******************************************************************
2933  * fill a notify_info_data with the attributes
2934  * jfm:xxxx a samba printer is always shared
2935  ********************************************************************/
2936
2937 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2938                                       int snum,
2939                                       struct spoolss_Notify *data,
2940                                       print_queue_struct *queue,
2941                                       struct spoolss_PrinterInfo2 *pinfo2,
2942                                       TALLOC_CTX *mem_ctx)
2943 {
2944         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2945 }
2946
2947 /*******************************************************************
2948  * fill a notify_info_data with the priority
2949  ********************************************************************/
2950
2951 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2952                                     int snum,
2953                                     struct spoolss_Notify *data,
2954                                     print_queue_struct *queue,
2955                                     struct spoolss_PrinterInfo2 *pinfo2,
2956                                     TALLOC_CTX *mem_ctx)
2957 {
2958         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2959 }
2960
2961 /*******************************************************************
2962  * fill a notify_info_data with the default priority
2963  ********************************************************************/
2964
2965 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2966                                             int snum,
2967                                             struct spoolss_Notify *data,
2968                                             print_queue_struct *queue,
2969                                             struct spoolss_PrinterInfo2 *pinfo2,
2970                                             TALLOC_CTX *mem_ctx)
2971 {
2972         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2973 }
2974
2975 /*******************************************************************
2976  * fill a notify_info_data with the start time
2977  ********************************************************************/
2978
2979 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2980                                       int snum,
2981                                       struct spoolss_Notify *data,
2982                                       print_queue_struct *queue,
2983                                       struct spoolss_PrinterInfo2 *pinfo2,
2984                                       TALLOC_CTX *mem_ctx)
2985 {
2986         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2987 }
2988
2989 /*******************************************************************
2990  * fill a notify_info_data with the until time
2991  ********************************************************************/
2992
2993 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
2994                                       int snum,
2995                                       struct spoolss_Notify *data,
2996                                       print_queue_struct *queue,
2997                                       struct spoolss_PrinterInfo2 *pinfo2,
2998                                       TALLOC_CTX *mem_ctx)
2999 {
3000         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3001 }
3002
3003 /*******************************************************************
3004  * fill a notify_info_data with the status
3005  ********************************************************************/
3006
3007 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3008                                   int snum,
3009                                   struct spoolss_Notify *data,
3010                                   print_queue_struct *queue,
3011                                   struct spoolss_PrinterInfo2 *pinfo2,
3012                                   TALLOC_CTX *mem_ctx)
3013 {
3014         print_status_struct status;
3015
3016         print_queue_length(msg_ctx, snum, &status);
3017         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3018 }
3019
3020 /*******************************************************************
3021  * fill a notify_info_data with the number of jobs queued
3022  ********************************************************************/
3023
3024 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3025                                  int snum,
3026                                  struct spoolss_Notify *data,
3027                                  print_queue_struct *queue,
3028                                  struct spoolss_PrinterInfo2 *pinfo2,
3029                                  TALLOC_CTX *mem_ctx)
3030 {
3031         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3032                 data, print_queue_length(msg_ctx, snum, NULL));
3033 }
3034
3035 /*******************************************************************
3036  * fill a notify_info_data with the average ppm
3037  ********************************************************************/
3038
3039 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3040                                        int snum,
3041                                        struct spoolss_Notify *data,
3042                                        print_queue_struct *queue,
3043                                        struct spoolss_PrinterInfo2 *pinfo2,
3044                                        TALLOC_CTX *mem_ctx)
3045 {
3046         /* always respond 8 pages per minutes */
3047         /* a little hard ! */
3048         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3049 }
3050
3051 /*******************************************************************
3052  * fill a notify_info_data with username
3053  ********************************************************************/
3054
3055 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3056                                     int snum,
3057                                     struct spoolss_Notify *data,
3058                                     print_queue_struct *queue,
3059                                     struct spoolss_PrinterInfo2 *pinfo2,
3060                                     TALLOC_CTX *mem_ctx)
3061 {
3062         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3063 }
3064
3065 /*******************************************************************
3066  * fill a notify_info_data with job status
3067  ********************************************************************/
3068
3069 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3070                                       int snum,
3071                                       struct spoolss_Notify *data,
3072                                       print_queue_struct *queue,
3073                                       struct spoolss_PrinterInfo2 *pinfo2,
3074                                       TALLOC_CTX *mem_ctx)
3075 {
3076         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3077 }
3078
3079 /*******************************************************************
3080  * fill a notify_info_data with job name
3081  ********************************************************************/
3082
3083 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3084                                     int snum,
3085                                     struct spoolss_Notify *data,
3086                                     print_queue_struct *queue,
3087                                     struct spoolss_PrinterInfo2 *pinfo2,
3088                                     TALLOC_CTX *mem_ctx)
3089 {
3090         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3091 }
3092
3093 /*******************************************************************
3094  * fill a notify_info_data with job status
3095  ********************************************************************/
3096
3097 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3098                                              int snum,
3099                                              struct spoolss_Notify *data,
3100                                              print_queue_struct *queue,
3101                                              struct spoolss_PrinterInfo2 *pinfo2,
3102                                              TALLOC_CTX *mem_ctx)
3103 {
3104         /*
3105          * Now we're returning job status codes we just return a "" here. JRA.
3106          */
3107
3108         const char *p = "";
3109
3110 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3111         p = "unknown";
3112
3113         switch (queue->status) {
3114         case LPQ_QUEUED:
3115                 p = "Queued";
3116                 break;
3117         case LPQ_PAUSED:
3118                 p = "";    /* NT provides the paused string */
3119                 break;
3120         case LPQ_SPOOLING:
3121                 p = "Spooling";
3122                 break;
3123         case LPQ_PRINTING:
3124                 p = "Printing";
3125                 break;
3126         }
3127 #endif /* NO LONGER NEEDED. */
3128
3129         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3130 }
3131
3132 /*******************************************************************
3133  * fill a notify_info_data with job time
3134  ********************************************************************/
3135
3136 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3137                                     int snum,
3138                                     struct spoolss_Notify *data,
3139                                     print_queue_struct *queue,
3140                                     struct spoolss_PrinterInfo2 *pinfo2,
3141                                     TALLOC_CTX *mem_ctx)
3142 {
3143         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3144 }
3145
3146 /*******************************************************************
3147  * fill a notify_info_data with job size
3148  ********************************************************************/
3149
3150 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3151                                     int snum,
3152                                     struct spoolss_Notify *data,
3153                                     print_queue_struct *queue,
3154                                     struct spoolss_PrinterInfo2 *pinfo2,
3155                                     TALLOC_CTX *mem_ctx)
3156 {
3157         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3158 }
3159
3160 /*******************************************************************
3161  * fill a notify_info_data with page info
3162  ********************************************************************/
3163 static void spoolss_notify_total_pages(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, queue->page_count);
3171 }
3172
3173 /*******************************************************************
3174  * fill a notify_info_data with pages printed info.
3175  ********************************************************************/
3176 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3177                                          int snum,
3178                                 struct spoolss_Notify *data,
3179                                 print_queue_struct *queue,
3180                                 struct spoolss_PrinterInfo2 *pinfo2,
3181                                 TALLOC_CTX *mem_ctx)
3182 {
3183         /* Add code when back-end tracks this */
3184         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3185 }
3186
3187 /*******************************************************************
3188  Fill a notify_info_data with job position.
3189  ********************************************************************/
3190
3191 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3192                                         int snum,
3193                                         struct spoolss_Notify *data,
3194                                         print_queue_struct *queue,
3195                                         struct spoolss_PrinterInfo2 *pinfo2,
3196                                         TALLOC_CTX *mem_ctx)
3197 {
3198         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3199 }
3200
3201 /*******************************************************************
3202  Fill a notify_info_data with submitted time.
3203  ********************************************************************/
3204
3205 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3206                                           int snum,
3207                                           struct spoolss_Notify *data,
3208                                           print_queue_struct *queue,
3209                                           struct spoolss_PrinterInfo2 *pinfo2,
3210                                           TALLOC_CTX *mem_ctx)
3211 {
3212         data->data.string.string = NULL;
3213         data->data.string.size = 0;
3214
3215         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3216                                &data->data.string.string,
3217                                &data->data.string.size);
3218
3219 }
3220
3221 struct s_notify_info_data_table
3222 {
3223         enum spoolss_NotifyType type;
3224         uint16_t field;
3225         const char *name;
3226         enum spoolss_NotifyTable variable_type;
3227         void (*fn) (struct messaging_context *msg_ctx,
3228                     int snum, struct spoolss_Notify *data,
3229                     print_queue_struct *queue,
3230                     struct spoolss_PrinterInfo2 *pinfo2,
3231                     TALLOC_CTX *mem_ctx);
3232 };
3233
3234 /* A table describing the various print notification constants and
3235    whether the notification data is a pointer to a variable sized
3236    buffer, a one value uint32_t or a two value uint32_t. */
3237
3238 static const struct s_notify_info_data_table notify_info_data_table[] =
3239 {
3240 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3241 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3242 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3243 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3244 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3245 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3246 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3247 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3248 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3249 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3250 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3251 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3252 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3253 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3254 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3266 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3267 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3268 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3269 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3270 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3271 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3272 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3273 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3274 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3275 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3276 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3277 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3278 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3279 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3280 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3281 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3282 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3283 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3284 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3285 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3286 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3287 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3288 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3289 };
3290
3291 /*******************************************************************
3292  Return the variable_type of info_data structure.
3293 ********************************************************************/
3294
3295 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3296                                                                   uint16_t field)
3297 {
3298         int i=0;
3299
3300         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3301                 if ( (notify_info_data_table[i].type == type) &&
3302                      (notify_info_data_table[i].field == field) ) {
3303                         return notify_info_data_table[i].variable_type;
3304                 }
3305         }
3306
3307         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3308
3309         return (enum spoolss_NotifyTable) 0;
3310 }
3311
3312 /****************************************************************************
3313 ****************************************************************************/
3314
3315 static bool search_notify(enum spoolss_NotifyType type,
3316                           uint16_t field,
3317                           int *value)
3318 {
3319         int i;
3320
3321         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3322                 if (notify_info_data_table[i].type == type &&
3323                     notify_info_data_table[i].field == field &&
3324                     notify_info_data_table[i].fn != NULL) {
3325                         *value = i;
3326                         return true;
3327                 }
3328         }
3329
3330         return false;
3331 }
3332
3333 /****************************************************************************
3334 ****************************************************************************/
3335
3336 static void construct_info_data(struct spoolss_Notify *info_data,
3337                                 enum spoolss_NotifyType type,
3338                                 uint16_t field, int id)
3339 {
3340         info_data->type                 = type;
3341         info_data->field.field          = field;
3342         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3343         info_data->job_id               = id;
3344 }
3345
3346 /*******************************************************************
3347  *
3348  * fill a notify_info struct with info asked
3349  *
3350  ********************************************************************/
3351
3352 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3353                                           struct printer_handle *print_hnd,
3354                                           struct spoolss_NotifyInfo *info,
3355                                           struct spoolss_PrinterInfo2 *pinfo2,
3356                                           int snum,
3357                                           const struct spoolss_NotifyOptionType *option_type,
3358                                           uint32_t id,
3359                                           TALLOC_CTX *mem_ctx)
3360 {
3361         int field_num,j;
3362         enum spoolss_NotifyType type;
3363         uint16_t field;
3364
3365         struct spoolss_Notify *current_data;
3366
3367         type = option_type->type;
3368
3369         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3370                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3371                 option_type->count, lp_servicename(talloc_tos(), snum)));
3372
3373         for(field_num=0; field_num < option_type->count; field_num++) {
3374                 field = option_type->fields[field_num].field;
3375
3376                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3377
3378                 if (!search_notify(type, field, &j) )
3379                         continue;
3380
3381                 info->notifies = talloc_realloc(info, info->notifies,
3382                                                       struct spoolss_Notify,
3383                                                       info->count + 1);
3384                 if (info->notifies == NULL) {
3385                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3386                         return false;
3387                 }
3388
3389                 current_data = &info->notifies[info->count];
3390
3391                 construct_info_data(current_data, type, field, id);
3392
3393                 DEBUG(10, ("construct_notify_printer_info: "
3394                            "calling [%s]  snum=%d  printername=[%s])\n",
3395                            notify_info_data_table[j].name, snum,
3396                            pinfo2->printername));
3397
3398                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3399                                              NULL, pinfo2, mem_ctx);
3400
3401                 info->count++;
3402         }
3403
3404         return true;
3405 }
3406
3407 /*******************************************************************
3408  *
3409  * fill a notify_info struct with info asked
3410  *
3411  ********************************************************************/
3412
3413 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3414                                        print_queue_struct *queue,
3415                                        struct spoolss_NotifyInfo *info,
3416                                        struct spoolss_PrinterInfo2 *pinfo2,
3417                                        int snum,
3418                                        const struct spoolss_NotifyOptionType *option_type,
3419                                        uint32_t id,
3420                                        TALLOC_CTX *mem_ctx)
3421 {
3422         int field_num,j;
3423         enum spoolss_NotifyType type;
3424         uint16_t field;
3425         struct spoolss_Notify *current_data;
3426
3427         DEBUG(4,("construct_notify_jobs_info\n"));
3428
3429         type = option_type->type;
3430
3431         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3432                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3433                 option_type->count));
3434
3435         for(field_num=0; field_num<option_type->count; field_num++) {
3436                 field = option_type->fields[field_num].field;
3437
3438                 if (!search_notify(type, field, &j) )
3439                         continue;
3440
3441                 info->notifies = talloc_realloc(info, info->notifies,
3442                                                       struct spoolss_Notify,
3443                                                       info->count + 1);
3444                 if (info->notifies == NULL) {
3445                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3446                         return false;
3447                 }
3448
3449                 current_data=&(info->notifies[info->count]);
3450
3451                 construct_info_data(current_data, type, field, id);
3452                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3453                                              queue, pinfo2, mem_ctx);
3454                 info->count++;
3455         }
3456
3457         return true;
3458 }
3459
3460 /*
3461  * JFM: The enumeration is not that simple, it's even non obvious.
3462  *
3463  * let's take an example: I want to monitor the PRINTER SERVER for
3464  * the printer's name and the number of jobs currently queued.
3465  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3466  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3467  *
3468  * I have 3 printers on the back of my server.
3469  *
3470  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3471  * structures.
3472  *   Number     Data                    Id
3473  *      1       printer 1 name          1
3474  *      2       printer 1 cjob          1
3475  *      3       printer 2 name          2
3476  *      4       printer 2 cjob          2
3477  *      5       printer 3 name          3
3478  *      6       printer 3 name          3
3479  *
3480  * that's the print server case, the printer case is even worse.
3481  */
3482
3483 /*******************************************************************
3484  *
3485  * enumerate all printers on the printserver
3486  * fill a notify_info struct with info asked
3487  *
3488  ********************************************************************/
3489
3490 static WERROR printserver_notify_info(struct pipes_struct *p,
3491                                       struct policy_handle *hnd,
3492                                       struct spoolss_NotifyInfo *info,
3493                                       TALLOC_CTX *mem_ctx)
3494 {
3495         int snum;
3496         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3497         int n_services=lp_numservices();
3498         int i;
3499         struct spoolss_NotifyOption *option;
3500         struct spoolss_NotifyOptionType option_type;
3501         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3502         WERROR result;
3503
3504         DEBUG(4,("printserver_notify_info\n"));
3505
3506         if (!Printer)
3507                 return WERR_INVALID_HANDLE;
3508
3509         option = Printer->notify.option;
3510
3511         info->version   = 2;
3512         info->notifies  = NULL;
3513         info->count     = 0;
3514
3515         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3516            sending a ffpcn() request first */
3517
3518         if ( !option )
3519                 return WERR_INVALID_HANDLE;
3520
3521         for (i=0; i<option->count; i++) {
3522                 option_type = option->types[i];
3523
3524                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3525                         continue;
3526
3527                 for (snum = 0; snum < n_services; snum++) {
3528                         if (!lp_browseable(snum) ||
3529                             !lp_snum_ok(snum) ||
3530                             !lp_printable(snum)) {
3531                                 continue; /* skip */
3532                         }
3533
3534                         /* Maybe we should use the SYSTEM session_info here... */
3535                         result = winreg_get_printer_internal(mem_ctx,
3536                                                     get_session_info_system(),
3537                                                     p->msg_ctx,
3538                                                     lp_servicename(talloc_tos(), snum),
3539                                                     &pinfo2);
3540                         if (!W_ERROR_IS_OK(result)) {
3541                                 DEBUG(4, ("printserver_notify_info: "
3542                                           "Failed to get printer [%s]\n",
3543                                           lp_servicename(talloc_tos(), snum)));
3544                                 continue;
3545                         }
3546
3547
3548                         construct_notify_printer_info(p->msg_ctx,
3549                                                       Printer, info,
3550                                                       pinfo2, snum,
3551                                                       &option_type, snum,
3552                                                       mem_ctx);
3553
3554                         TALLOC_FREE(pinfo2);
3555                 }
3556         }
3557
3558 #if 0
3559         /*
3560          * Debugging information, don't delete.
3561          */
3562
3563         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3564         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3565         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3566
3567         for (i=0; i<info->count; i++) {
3568                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3569                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3570                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3571         }
3572 #endif
3573
3574         return WERR_OK;
3575 }
3576
3577 /*******************************************************************
3578  *
3579  * fill a notify_info struct with info asked
3580  *
3581  ********************************************************************/
3582
3583 static WERROR printer_notify_info(struct pipes_struct *p,
3584                                   struct policy_handle *hnd,
3585                                   struct spoolss_NotifyInfo *info,
3586                                   TALLOC_CTX *mem_ctx)
3587 {
3588         int snum;
3589         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3590         int i;
3591         uint32_t id;
3592         struct spoolss_NotifyOption *option;
3593         struct spoolss_NotifyOptionType option_type;
3594         int count,j;
3595         print_queue_struct *queue=NULL;
3596         print_status_struct status;
3597         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3598         WERROR result;
3599         struct tdb_print_db *pdb;
3600
3601         DEBUG(4,("printer_notify_info\n"));
3602
3603         if (!Printer)
3604                 return WERR_INVALID_HANDLE;
3605
3606         option = Printer->notify.option;
3607         id = 0x0;
3608
3609         info->version   = 2;
3610         info->notifies  = NULL;
3611         info->count     = 0;
3612
3613         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3614            sending a ffpcn() request first */
3615
3616         if ( !option )
3617                 return WERR_INVALID_HANDLE;
3618
3619         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3620                 return WERR_INVALID_HANDLE;
3621         }
3622
3623         pdb = get_print_db_byname(Printer->sharename);
3624         if (pdb == NULL) {
3625                 return WERR_INVALID_HANDLE;
3626         }
3627
3628         /* Maybe we should use the SYSTEM session_info here... */
3629         result = winreg_get_printer_internal(mem_ctx,
3630                                     get_session_info_system(),
3631                                     p->msg_ctx,
3632                                     lp_servicename(talloc_tos(), snum), &pinfo2);
3633         if (!W_ERROR_IS_OK(result)) {
3634                 result = WERR_INVALID_HANDLE;
3635                 goto err_pdb_drop;
3636         }
3637
3638         /*
3639          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3640          * correct servername.
3641          */
3642         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3643         if (pinfo2->servername == NULL) {
3644                 result = WERR_NOT_ENOUGH_MEMORY;
3645                 goto err_pdb_drop;
3646         }
3647
3648         for (i = 0; i < option->count; i++) {
3649                 option_type = option->types[i];
3650
3651                 switch (option_type.type) {
3652                 case PRINTER_NOTIFY_TYPE:
3653                         if (construct_notify_printer_info(p->msg_ctx,
3654                                                           Printer, info,
3655                                                           pinfo2, snum,
3656                                                           &option_type, id,
3657                                                           mem_ctx)) {
3658                                 id--;
3659                         }
3660                         break;
3661
3662                 case JOB_NOTIFY_TYPE:
3663
3664                         count = print_queue_status(p->msg_ctx, snum, &queue,
3665                                                    &status);
3666
3667                         for (j = 0; j < count; j++) {
3668                                 uint32_t jobid;
3669                                 jobid = sysjob_to_jobid_pdb(pdb,
3670                                                             queue[j].sysjob);
3671                                 if (jobid == (uint32_t)-1) {
3672                                         DEBUG(2, ("ignoring untracked job %d\n",
3673                                                   queue[j].sysjob));
3674                                         continue;
3675                                 }
3676                                 /* FIXME check return value */
3677                                 construct_notify_jobs_info(p->msg_ctx,
3678                                                            &queue[j], info,
3679                                                            pinfo2, snum,
3680                                                            &option_type,
3681                                                            jobid,
3682                                                            mem_ctx);
3683                         }
3684
3685                         SAFE_FREE(queue);
3686                         break;
3687                 }
3688         }
3689
3690         /*
3691          * Debugging information, don't delete.
3692          */
3693         /*
3694         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3695         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3696         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3697
3698         for (i=0; i<info->count; i++) {
3699                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3700                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3701                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3702         }
3703         */
3704
3705         talloc_free(pinfo2);
3706         result = WERR_OK;
3707 err_pdb_drop:
3708         release_print_db(pdb);
3709         return result;
3710 }
3711
3712 /****************************************************************
3713  _spoolss_RouterRefreshPrinterChangeNotify
3714 ****************************************************************/
3715
3716 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3717                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3718 {
3719         struct spoolss_NotifyInfo *info;
3720
3721         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3722         WERROR result = WERR_INVALID_HANDLE;
3723
3724         /* we always have a spoolss_NotifyInfo struct */
3725         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3726         if (!info) {
3727                 result = WERR_NOT_ENOUGH_MEMORY;
3728                 goto done;
3729         }
3730
3731         *r->out.info = info;
3732
3733         if (!Printer) {
3734                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3735                         "Invalid handle (%s:%u:%u).\n",
3736                         OUR_HANDLE(r->in.handle)));
3737                 goto done;
3738         }
3739
3740         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3741
3742         /*
3743          *      We are now using the change value, and
3744          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3745          *      I don't have a global notification system, I'm sending back all the
3746          *      information even when _NOTHING_ has changed.
3747          */
3748
3749         /* We need to keep track of the change value to send back in
3750            RRPCN replies otherwise our updates are ignored. */
3751
3752         Printer->notify.fnpcn = true;
3753
3754         if (Printer->notify.cli_chan != NULL &&
3755             Printer->notify.cli_chan->active_connections > 0) {
3756                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3757                         "Saving change value in request [%x]\n",
3758                         r->in.change_low));
3759                 Printer->notify.change = r->in.change_low;
3760         }
3761
3762         /* just ignore the spoolss_NotifyOption */
3763
3764         switch (Printer->printer_type) {
3765                 case SPLHND_SERVER:
3766                         result = printserver_notify_info(p, r->in.handle,
3767                                                          info, p->mem_ctx);
3768                         break;
3769
3770                 case SPLHND_PRINTER:
3771                         result = printer_notify_info(p, r->in.handle,
3772                                                      info, p->mem_ctx);
3773                         break;
3774         }
3775
3776         Printer->notify.fnpcn = false;
3777
3778 done:
3779         return result;
3780 }
3781
3782 /********************************************************************
3783  ********************************************************************/
3784
3785 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3786                                  const char *servername,
3787                                  const char *printername,
3788                                  const char **printername_p)
3789 {
3790         /* FIXME: add lp_force_printername() */
3791
3792         if (servername == NULL) {
3793                 *printername_p = talloc_strdup(mem_ctx, printername);
3794                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3795                 return WERR_OK;
3796         }
3797
3798         if (servername[0] == '\\' && servername[1] == '\\') {
3799                 servername += 2;
3800         }
3801
3802         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3803         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3804
3805         return WERR_OK;
3806 }
3807
3808 /********************************************************************
3809  ********************************************************************/
3810
3811 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3812                                           const char *printername)
3813 {
3814         if (dm == NULL) {
3815                 return;
3816         }
3817
3818         dm->devicename = talloc_strndup(dm, printername,
3819                                         MIN(strlen(printername), 31));
3820 }
3821
3822 /********************************************************************
3823  * construct_printer_info_0
3824  * fill a printer_info_0 struct
3825  ********************************************************************/
3826
3827 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3828                                       const struct auth_session_info *session_info,
3829                                       struct messaging_context *msg_ctx,
3830                                       struct spoolss_PrinterInfo2 *info2,
3831                                       const char *servername,
3832                                       struct spoolss_PrinterInfo0 *r,
3833                                       int snum)
3834 {
3835         int count;
3836         struct printer_session_counter *session_counter;
3837         struct timeval setuptime;
3838         print_status_struct status;
3839         WERROR result;
3840         int os_major, os_minor, os_build;
3841         const char *architecture;
3842         uint32_t processor_architecture, processor_type;
3843
3844         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3845         if (!W_ERROR_IS_OK(result)) {
3846                 return result;
3847         }
3848
3849         if (servername) {
3850                 r->servername = talloc_strdup(mem_ctx, servername);
3851                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3852         } else {
3853                 r->servername = NULL;
3854         }
3855
3856         count = print_queue_length(msg_ctx, snum, &status);
3857
3858         /* check if we already have a counter for this printer */
3859         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3860                 if (session_counter->snum == snum)
3861                         break;
3862         }
3863
3864         /* it's the first time, add it to the list */
3865         if (session_counter == NULL) {
3866                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3867                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3868                 session_counter->snum           = snum;
3869                 session_counter->counter        = 0;
3870                 DLIST_ADD(counter_list, session_counter);
3871         }
3872
3873         /* increment it */
3874         session_counter->counter++;
3875
3876         r->cjobs                        = count;
3877         r->total_jobs                   = 0;
3878         r->total_bytes                  = 0;
3879
3880         get_startup_time(&setuptime);
3881         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3882
3883         /* JFM:
3884          * the global_counter should be stored in a TDB as it's common to all the clients
3885          * and should be zeroed on samba startup
3886          */
3887         r->global_counter               = session_counter->counter;
3888         r->total_pages                  = 0;
3889
3890         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3891         os_major = lp_parm_int(GLOBAL_SECTION_SNUM,
3892                                "spoolss", "os_major",
3893                                GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
3894         os_minor = lp_parm_int(GLOBAL_SECTION_SNUM,
3895                                "spoolss", "os_minor",
3896                                GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
3897         os_build = lp_parm_int(GLOBAL_SECTION_SNUM,
3898                                "spoolss", "os_build",
3899                                GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
3900
3901         SCVAL(&r->version, 0, os_major);
3902         SCVAL(&r->version, 1, os_minor);
3903         SSVAL(&r->version, 2, os_build);
3904
3905         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
3906                                             "spoolss",
3907                                             "architecture",
3908                                             GLOBAL_SPOOLSS_ARCHITECTURE);
3909
3910         if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
3911                 processor_architecture  = PROCESSOR_ARCHITECTURE_AMD64;
3912                 processor_type          = PROCESSOR_AMD_X8664;
3913         } else {
3914                 processor_architecture  = PROCESSOR_ARCHITECTURE_INTEL;
3915                 processor_type          = PROCESSOR_INTEL_PENTIUM;
3916         }
3917
3918         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3919         r->spooling                     = 0;
3920         r->max_spooling                 = 0;
3921         r->session_counter              = session_counter->counter;
3922         r->num_error_out_of_paper       = 0x0;
3923         r->num_error_not_ready          = 0x0;          /* number of print failure */
3924         r->job_error                    = 0x0;
3925         r->number_of_processors         = 0x1;
3926         r->processor_type               = processor_type;
3927         r->high_part_total_bytes        = 0x0;
3928
3929         /* ChangeID in milliseconds*/
3930         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3931                                     info2->sharename, &r->change_id);
3932
3933         r->last_error                   = WERR_OK;
3934         r->status                       = nt_printq_status(status.status);
3935         r->enumerate_network_printers   = 0x0;
3936         r->c_setprinter                 = 0x0;
3937         r->processor_architecture       = processor_architecture;
3938         r->processor_level              = 0x6;          /* 6  ???*/
3939         r->ref_ic                       = 0;
3940         r->reserved2                    = 0;
3941         r->reserved3                    = 0;
3942
3943         return WERR_OK;
3944 }
3945
3946
3947 /********************************************************************
3948  * construct_printer_info1
3949  * fill a spoolss_PrinterInfo1 struct
3950 ********************************************************************/
3951
3952 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3953                                       const struct spoolss_PrinterInfo2 *info2,
3954                                       uint32_t flags,
3955                                       const char *servername,
3956                                       struct spoolss_PrinterInfo1 *r,
3957                                       int snum)
3958 {
3959         WERROR result;
3960
3961         r->flags                = flags;
3962
3963         if (info2->comment == NULL || info2->comment[0] == '\0') {
3964                 r->comment      = lp_comment(mem_ctx, snum);
3965         } else {
3966                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3967         }
3968         W_ERROR_HAVE_NO_MEMORY(r->comment);
3969
3970         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3971         if (!W_ERROR_IS_OK(result)) {
3972                 return result;
3973         }
3974
3975         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3976                                                   r->name,
3977                                                   info2->drivername,
3978                                                   r->comment);
3979         W_ERROR_HAVE_NO_MEMORY(r->description);
3980
3981         return WERR_OK;
3982 }
3983
3984 /********************************************************************
3985  * construct_printer_info2
3986  * fill a spoolss_PrinterInfo2 struct
3987 ********************************************************************/
3988
3989 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3990                                       struct messaging_context *msg_ctx,
3991                                       const struct spoolss_PrinterInfo2 *info2,
3992                                       const char *servername,
3993                                       struct spoolss_PrinterInfo2 *r,
3994                                       int snum)
3995 {
3996         int count;
3997         print_status_struct status;
3998         WERROR result;
3999
4000         count = print_queue_length(msg_ctx, snum, &status);
4001
4002         if (servername) {
4003                 r->servername           = talloc_strdup(mem_ctx, servername);
4004                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4005         } else {
4006                 r->servername           = NULL;
4007         }
4008
4009         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4010         if (!W_ERROR_IS_OK(result)) {
4011                 return result;
4012         }
4013
4014         r->sharename            = lp_servicename(mem_ctx, snum);
4015         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4016         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4017         W_ERROR_HAVE_NO_MEMORY(r->portname);
4018         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4019         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4020
4021         if (info2->comment[0] == '\0') {
4022                 r->comment      = lp_comment(mem_ctx, snum);
4023         } else {
4024                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4025         }
4026         W_ERROR_HAVE_NO_MEMORY(r->comment);
4027
4028         r->location     = talloc_strdup(mem_ctx, info2->location);
4029         if (info2->location[0] == '\0') {
4030                 const char *loc = NULL;
4031                 NTSTATUS nt_status;
4032
4033                 nt_status = printer_list_get_printer(mem_ctx,
4034                                                      info2->sharename,
4035                                                      NULL,
4036                                                      &loc,
4037                                                      NULL);
4038                 if (NT_STATUS_IS_OK(nt_status)) {
4039                         if (loc != NULL) {
4040                                 r->location = talloc_strdup(mem_ctx, loc);
4041                         }
4042                 }
4043         }
4044         W_ERROR_HAVE_NO_MEMORY(r->location);
4045
4046         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4047         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4048         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4049         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4050         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4051         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4052         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4053         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4054
4055         r->attributes           = info2->attributes;
4056
4057         r->priority             = info2->priority;
4058         r->defaultpriority      = info2->defaultpriority;
4059         r->starttime            = info2->starttime;
4060         r->untiltime            = info2->untiltime;
4061         r->status               = nt_printq_status(status.status);
4062         r->cjobs                = count;
4063         r->averageppm           = info2->averageppm;
4064
4065         if (info2->devmode != NULL) {
4066                 result = copy_devicemode(mem_ctx,
4067                                          info2->devmode,
4068                                          &r->devmode);
4069                 if (!W_ERROR_IS_OK(result)) {
4070                         return result;
4071                 }
4072         } else if (lp_default_devmode(snum)) {
4073                 result = spoolss_create_default_devmode(mem_ctx,
4074                                                         info2->printername,
4075                                                         &r->devmode);
4076                 if (!W_ERROR_IS_OK(result)) {
4077                         return result;
4078                 }
4079         } else {
4080                 r->devmode = NULL;
4081                 DEBUG(8,("Returning NULL Devicemode!\n"));
4082         }
4083
4084         compose_devicemode_devicename(r->devmode, r->printername);
4085
4086         r->secdesc = NULL;
4087
4088         if (info2->secdesc != NULL) {
4089                 /* don't use talloc_steal() here unless you do a deep steal of all
4090                    the SEC_DESC members */
4091
4092                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4093                 if (r->secdesc == NULL) {
4094                         return WERR_NOT_ENOUGH_MEMORY;
4095                 }
4096         }
4097
4098         return WERR_OK;
4099 }
4100
4101 /********************************************************************
4102  * construct_printer_info3
4103  * fill a spoolss_PrinterInfo3 struct
4104  ********************************************************************/
4105
4106 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4107                                       const struct spoolss_PrinterInfo2 *info2,
4108                                       const char *servername,
4109                                       struct spoolss_PrinterInfo3 *r,
4110                                       int snum)
4111 {
4112         /* These are the components of the SD we are returning. */
4113
4114         if (info2->secdesc != NULL) {
4115                 /* don't use talloc_steal() here unless you do a deep steal of all
4116                    the SEC_DESC members */
4117
4118                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4119                 if (r->secdesc == NULL) {
4120                         return WERR_NOT_ENOUGH_MEMORY;
4121                 }
4122         }
4123
4124         return WERR_OK;
4125 }
4126
4127 /********************************************************************
4128  * construct_printer_info4
4129  * fill a spoolss_PrinterInfo4 struct
4130  ********************************************************************/
4131
4132 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4133                                       const struct spoolss_PrinterInfo2 *info2,
4134                                       const char *servername,
4135                                       struct spoolss_PrinterInfo4 *r,
4136                                       int snum)
4137 {
4138         WERROR result;
4139
4140         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4141         if (!W_ERROR_IS_OK(result)) {
4142                 return result;
4143         }
4144
4145         if (servername) {
4146                 r->servername   = talloc_strdup(mem_ctx, servername);
4147                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4148         } else {
4149                 r->servername = NULL;
4150         }
4151
4152         r->attributes   = info2->attributes;
4153
4154         return WERR_OK;
4155 }
4156
4157 /********************************************************************
4158  * construct_printer_info5
4159  * fill a spoolss_PrinterInfo5 struct
4160  ********************************************************************/
4161
4162 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4163                                       const struct spoolss_PrinterInfo2 *info2,
4164                                       const char *servername,
4165                                       struct spoolss_PrinterInfo5 *r,
4166                                       int snum)
4167 {
4168         WERROR result;
4169
4170         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4171         if (!W_ERROR_IS_OK(result)) {
4172                 return result;
4173         }
4174
4175         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4176         W_ERROR_HAVE_NO_MEMORY(r->portname);
4177
4178         r->attributes   = info2->attributes;
4179
4180         /* these two are not used by NT+ according to MSDN */
4181         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4182         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4183
4184         return WERR_OK;
4185 }
4186
4187 /********************************************************************
4188  * construct_printer_info_6
4189  * fill a spoolss_PrinterInfo6 struct
4190  ********************************************************************/
4191
4192 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4193                                       struct messaging_context *msg_ctx,
4194                                       const struct spoolss_PrinterInfo2 *info2,
4195                                       const char *servername,
4196                                       struct spoolss_PrinterInfo6 *r,
4197                                       int snum)
4198 {
4199         print_status_struct status;
4200
4201         print_queue_length(msg_ctx, snum, &status);
4202
4203         r->status = nt_printq_status(status.status);
4204
4205         return WERR_OK;
4206 }
4207
4208 /********************************************************************
4209  * construct_printer_info7
4210  * fill a spoolss_PrinterInfo7 struct
4211  ********************************************************************/
4212
4213 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4214                                       struct messaging_context *msg_ctx,
4215                                       const char *servername,
4216                                       struct spoolss_PrinterInfo7 *r,
4217                                       int snum)
4218 {
4219         const struct auth_session_info *session_info;
4220         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4221         char *printer;
4222         WERROR werr;
4223         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4224         if (tmp_ctx == NULL) {
4225                 return WERR_NOT_ENOUGH_MEMORY;
4226         }
4227
4228         session_info = get_session_info_system();
4229         SMB_ASSERT(session_info != NULL);
4230
4231         printer = lp_servicename(tmp_ctx, snum);
4232         if (printer == NULL) {
4233                 DEBUG(0, ("invalid printer snum %d\n", snum));
4234                 werr = WERR_INVALID_PARAMETER;
4235                 goto out_tmp_free;
4236         }
4237
4238         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4239                                  servername, printer, &pinfo2)) {
4240                 struct GUID guid;
4241                 struct GUID_txt_buf guid_txt;
4242                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4243                                            printer, &guid);
4244                 if (!W_ERROR_IS_OK(werr)) {
4245                         /*
4246                          * If we do not have a GUID entry in the registry, then
4247                          * try to retrieve it from AD and store it now.
4248                          */
4249                         werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4250                                                         &guid);
4251                         if (!W_ERROR_IS_OK(werr)) {
4252                                 DBG_NOTICE("Failed to retrieve GUID for "
4253                                            "printer [%s] from AD - %s\n",
4254                                            printer,
4255                                            win_errstr(werr));
4256                                 if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
4257                                         /*
4258                                          * If we did not find it in AD, then it
4259                                          * is unpublished and we should reflect
4260                                          * this in the registry and return
4261                                          * success.
4262                                          */
4263                                         DBG_WARNING("Unpublish printer [%s]\n",
4264                                                     pinfo2->sharename);
4265                                         nt_printer_publish(tmp_ctx,
4266                                                            session_info,
4267                                                            msg_ctx,
4268                                                            pinfo2,
4269                                                            DSPRINT_UNPUBLISH);
4270                                         r->guid = talloc_strdup(mem_ctx, "");
4271                                         r->action = DSPRINT_UNPUBLISH;
4272
4273                                         if (r->guid == NULL) {
4274                                                 werr = WERR_NOT_ENOUGH_MEMORY;
4275                                         } else {
4276                                                 werr = WERR_OK;
4277                                         }
4278                                 }
4279                                 goto out_tmp_free;
4280                         }
4281
4282                         werr = nt_printer_guid_store(msg_ctx, printer, guid);
4283                         if (!W_ERROR_IS_OK(werr)) {
4284                                 DEBUG(3, ("failed to store printer %s guid\n",
4285                                           printer));
4286                         }
4287                 }
4288                 r->guid = talloc_strdup_upper(mem_ctx,
4289                                              GUID_buf_string(&guid, &guid_txt));
4290                 r->action = DSPRINT_PUBLISH;
4291         } else {
4292                 r->guid = talloc_strdup(mem_ctx, "");
4293                 r->action = DSPRINT_UNPUBLISH;
4294         }
4295         if (r->guid == NULL) {
4296                 werr = WERR_NOT_ENOUGH_MEMORY;
4297                 goto out_tmp_free;
4298         }
4299
4300         werr = WERR_OK;
4301 out_tmp_free:
4302         talloc_free(tmp_ctx);
4303         return werr;
4304 }
4305
4306 /********************************************************************
4307  * construct_printer_info8
4308  * fill a spoolss_PrinterInfo8 struct
4309  ********************************************************************/
4310
4311 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4312                                       const struct spoolss_PrinterInfo2 *info2,
4313                                       const char *servername,
4314                                       struct spoolss_DeviceModeInfo *r,
4315                                       int snum)
4316 {
4317         WERROR result;
4318         const char *printername;
4319
4320         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4321         if (!W_ERROR_IS_OK(result)) {
4322                 return result;
4323         }
4324
4325         if (info2->devmode != NULL) {
4326                 result = copy_devicemode(mem_ctx,
4327                                          info2->devmode,
4328                                          &r->devmode);
4329                 if (!W_ERROR_IS_OK(result)) {
4330                         return result;
4331                 }
4332         } else if (lp_default_devmode(snum)) {
4333                 result = spoolss_create_default_devmode(mem_ctx,
4334                                                         info2->printername,
4335                                                         &r->devmode);
4336                 if (!W_ERROR_IS_OK(result)) {
4337                         return result;
4338                 }
4339         } else {
4340                 r->devmode = NULL;
4341                 DEBUG(8,("Returning NULL Devicemode!\n"));
4342         }
4343
4344         compose_devicemode_devicename(r->devmode, printername);
4345
4346         return WERR_OK;
4347 }
4348
4349 /********************************************************************
4350  Spoolss_enumprinters.
4351 ********************************************************************/
4352
4353 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4354                                            const struct auth_session_info *session_info,
4355                                            struct messaging_context *msg_ctx,
4356                                            const char *servername,
4357                                            uint32_t level,
4358                                            uint32_t flags,
4359                                            union spoolss_PrinterInfo **info_p,
4360                                            uint32_t *count_p)
4361 {
4362         int snum;
4363         int n_services;
4364         union spoolss_PrinterInfo *info = NULL;
4365         uint32_t count = 0;
4366         WERROR result = WERR_OK;
4367         struct dcerpc_binding_handle *b = NULL;
4368         TALLOC_CTX *tmp_ctx = NULL;
4369
4370         tmp_ctx = talloc_new(mem_ctx);
4371         if (!tmp_ctx) {
4372                 return WERR_NOT_ENOUGH_MEMORY;
4373         }
4374
4375         /*
4376          * printer shares are updated on client enumeration. The background
4377          * printer process updates printer_list.tdb at regular intervals.
4378          */
4379         become_root();
4380         delete_and_reload_printers(server_event_context(), msg_ctx);
4381         unbecome_root();
4382
4383         n_services = lp_numservices();
4384         *count_p = 0;
4385         *info_p = NULL;
4386
4387         for (snum = 0; snum < n_services; snum++) {
4388
4389                 const char *printer;
4390                 struct spoolss_PrinterInfo2 *info2;
4391
4392                 if (!snum_is_shared_printer(snum)) {
4393                         continue;
4394                 }
4395
4396                 printer = lp_const_servicename(snum);
4397
4398                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4399                         printer, snum));
4400
4401                 if (b == NULL) {
4402                         result = winreg_printer_binding_handle(tmp_ctx,
4403                                                                session_info,
4404                                                                msg_ctx,
4405                                                                &b);
4406                         if (!W_ERROR_IS_OK(result)) {
4407                                 goto out;
4408                         }
4409                 }
4410
4411                 result = winreg_create_printer(tmp_ctx, b,
4412                                                printer);
4413                 if (!W_ERROR_IS_OK(result)) {
4414                         goto out;
4415                 }
4416
4417                 info = talloc_realloc(tmp_ctx, info,
4418                                             union spoolss_PrinterInfo,
4419                                             count + 1);
4420                 if (!info) {
4421                         result = WERR_NOT_ENOUGH_MEMORY;
4422                         goto out;
4423                 }
4424
4425                 result = winreg_get_printer(tmp_ctx, b,
4426                                             printer, &info2);
4427                 if (!W_ERROR_IS_OK(result)) {
4428                         goto out;
4429                 }
4430
4431                 switch (level) {
4432                 case 0:
4433                         result = construct_printer_info0(info, session_info,
4434                                                          msg_ctx, info2,
4435                                                          servername,
4436                                                          &info[count].info0, snum);
4437                         break;
4438                 case 1:
4439                         result = construct_printer_info1(info, info2, flags,
4440                                                          servername,
4441                                                          &info[count].info1, snum);
4442                         break;
4443                 case 2:
4444                         result = construct_printer_info2(info, msg_ctx, info2,
4445                                                          servername,
4446                                                          &info[count].info2, snum);
4447                         break;
4448                 case 4:
4449                         result = construct_printer_info4(info, info2,
4450                                                          servername,
4451                                                          &info[count].info4, snum);
4452                         break;
4453                 case 5:
4454                         result = construct_printer_info5(info, info2,
4455                                                          servername,
4456                                                          &info[count].info5, snum);
4457                         break;
4458
4459                 default:
4460                         result = WERR_INVALID_LEVEL;
4461                         goto out;
4462                 }
4463
4464                 if (!W_ERROR_IS_OK(result)) {
4465                         goto out;
4466                 }
4467
4468                 count++;
4469         }
4470
4471 out:
4472         if (W_ERROR_IS_OK(result)) {
4473                 *info_p = talloc_move(mem_ctx, &info);
4474                 *count_p = count;
4475         }
4476
4477         talloc_free(tmp_ctx);
4478
4479         return result;
4480 }
4481
4482 /********************************************************************
4483  * handle enumeration of printers at level 0
4484  ********************************************************************/
4485
4486 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4487                                   const struct auth_session_info *session_info,
4488                                   struct messaging_context *msg_ctx,
4489                                   uint32_t flags,
4490                                   const char *servername,
4491                                   union spoolss_PrinterInfo **info,
4492                                   uint32_t *count)
4493 {
4494         DEBUG(4,("enum_all_printers_info_0\n"));
4495
4496         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4497                                             servername, 0, flags, info, count);
4498 }
4499
4500
4501 /********************************************************************
4502 ********************************************************************/
4503
4504 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4505                                        const struct auth_session_info *session_info,
4506                                        struct messaging_context *msg_ctx,
4507                                        const char *servername,
4508                                        uint32_t flags,
4509                                        union spoolss_PrinterInfo **info,
4510                                        uint32_t *count)
4511 {
4512         DEBUG(4,("enum_all_printers_info_1\n"));
4513
4514         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4515                                             servername, 1, flags, info, count);
4516 }
4517
4518 /********************************************************************
4519  enum_all_printers_info_1_local.
4520 *********************************************************************/
4521
4522 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4523                                              const struct auth_session_info *session_info,
4524                                              struct messaging_context *msg_ctx,
4525                                              const char *servername,
4526                                              union spoolss_PrinterInfo **info,
4527                                              uint32_t *count)
4528 {
4529         DEBUG(4,("enum_all_printers_info_1_local\n"));
4530
4531         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4532                                         servername, PRINTER_ENUM_ICON8, info, count);
4533 }
4534
4535 /********************************************************************
4536  enum_all_printers_info_1_name.
4537 *********************************************************************/
4538
4539 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4540                                             const struct auth_session_info *session_info,
4541                                             struct messaging_context *msg_ctx,
4542                                             const char *servername,
4543                                             union spoolss_PrinterInfo **info,
4544                                             uint32_t *count)
4545 {
4546         const char *s = servername;
4547
4548         DEBUG(4,("enum_all_printers_info_1_name\n"));
4549
4550         if (servername != NULL &&
4551             (servername[0] == '\\') && (servername[1] == '\\')) {
4552                 s = servername + 2;
4553         }
4554
4555         if (!is_myname_or_ipaddr(s)) {
4556                 return WERR_INVALID_NAME;
4557         }
4558
4559         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4560                                         servername, PRINTER_ENUM_ICON8, info, count);
4561 }
4562
4563 /********************************************************************
4564  enum_all_printers_info_1_network.
4565 *********************************************************************/
4566
4567 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4568                                                const struct auth_session_info *session_info,
4569                                                struct messaging_context *msg_ctx,
4570                                                const char *servername,
4571                                                union spoolss_PrinterInfo **info,
4572                                                uint32_t *count)
4573 {
4574         const char *s = servername;
4575
4576         DEBUG(4,("enum_all_printers_info_1_network\n"));
4577
4578         /* If we respond to a enum_printers level 1 on our name with flags
4579            set to PRINTER_ENUM_REMOTE with a list of printers then these
4580            printers incorrectly appear in the APW browse list.
4581            Specifically the printers for the server appear at the workgroup
4582            level where all the other servers in the domain are
4583            listed. Windows responds to this call with a
4584            WERR_CAN_NOT_COMPLETE so we should do the same. */
4585
4586         if (servername != NULL &&
4587             (servername[0] == '\\') && (servername[1] == '\\')) {
4588                  s = servername + 2;
4589         }
4590
4591         if (is_myname_or_ipaddr(s)) {
4592                  return WERR_CAN_NOT_COMPLETE;
4593         }
4594
4595         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4596                                         servername, PRINTER_ENUM_NAME, info, count);
4597 }
4598
4599 /********************************************************************
4600  * api_spoolss_enumprinters
4601  *
4602  * called from api_spoolss_enumprinters (see this to understand)
4603  ********************************************************************/
4604
4605 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4606                                        const struct auth_session_info *session_info,
4607                                        struct messaging_context *msg_ctx,
4608                                        const char *servername,
4609                                        union spoolss_PrinterInfo **info,
4610                                        uint32_t *count)
4611 {
4612         DEBUG(4,("enum_all_printers_info_2\n"));
4613
4614         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4615                                             servername, 2, 0, info, count);
4616 }
4617
4618 /********************************************************************
4619  * handle enumeration of printers at level 1
4620  ********************************************************************/
4621
4622 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4623                                   const struct auth_session_info *session_info,
4624                                   struct messaging_context *msg_ctx,
4625                                   uint32_t flags,
4626                                   const char *servername,
4627                                   union spoolss_PrinterInfo **info,
4628                                   uint32_t *count)
4629 {
4630         /* Not all the flags are equals */
4631
4632         if (flags & PRINTER_ENUM_LOCAL) {
4633                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4634                                                       msg_ctx, servername, info, count);
4635         }
4636
4637         if (flags & PRINTER_ENUM_NAME) {
4638                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4639                                                      msg_ctx, servername, info,
4640                                                      count);
4641         }
4642
4643         if (flags & PRINTER_ENUM_NETWORK) {
4644                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4645                                                         msg_ctx, servername, info,
4646                                                         count);
4647         }
4648
4649         return WERR_OK; /* NT4sp5 does that */
4650 }
4651
4652 /********************************************************************
4653  * handle enumeration of printers at level 2
4654  ********************************************************************/
4655
4656 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4657                                   const struct auth_session_info *session_info,
4658                                   struct messaging_context *msg_ctx,
4659                                   uint32_t flags,
4660                                   const char *servername,
4661                                   union spoolss_PrinterInfo **info,
4662                                   uint32_t *count)
4663 {
4664         if (flags & PRINTER_ENUM_LOCAL) {
4665
4666                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4667                                                 servername,
4668                                                 info, count);
4669         }
4670
4671         if (flags & PRINTER_ENUM_NAME) {
4672                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4673                         return WERR_INVALID_NAME;
4674                 }
4675
4676                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4677                                                 servername,
4678                                                 info, count);
4679         }
4680
4681         if (flags & PRINTER_ENUM_REMOTE) {
4682                 return WERR_INVALID_LEVEL;
4683         }
4684
4685         return WERR_OK;
4686 }
4687
4688 /********************************************************************
4689  * handle enumeration of printers at level 4
4690  ********************************************************************/
4691
4692 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4693                                   const struct auth_session_info *session_info,
4694                                   struct messaging_context *msg_ctx,
4695                                   uint32_t flags,
4696                                   const char *servername,
4697                                   union spoolss_PrinterInfo **info,
4698                                   uint32_t *count)
4699 {
4700         DEBUG(4,("enum_all_printers_info_4\n"));
4701
4702         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4703                                             servername, 4, flags, info, count);
4704 }
4705
4706
4707 /********************************************************************
4708  * handle enumeration of printers at level 5
4709  ********************************************************************/
4710
4711 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4712                                   const struct auth_session_info *session_info,
4713                                   struct messaging_context *msg_ctx,
4714                                   uint32_t flags,
4715                                   const char *servername,
4716                                   union spoolss_PrinterInfo **info,
4717                                   uint32_t *count)
4718 {
4719         DEBUG(4,("enum_all_printers_info_5\n"));
4720
4721         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4722                                             servername, 5, flags, info, count);
4723 }
4724
4725 /****************************************************************
4726  _spoolss_EnumPrinters
4727 ****************************************************************/
4728
4729 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4730                              struct spoolss_EnumPrinters *r)
4731 {
4732         const struct auth_session_info *session_info = get_session_info_system();
4733         WERROR result;
4734
4735         /* that's an [in out] buffer */
4736
4737         if (!r->in.buffer && (r->in.offered != 0)) {
4738                 return WERR_INVALID_PARAMETER;
4739         }
4740
4741         DEBUG(4,("_spoolss_EnumPrinters\n"));
4742
4743         *r->out.needed = 0;
4744         *r->out.count = 0;
4745         *r->out.info = NULL;
4746
4747         /*
4748          * Level 1:
4749          *          flags==PRINTER_ENUM_NAME
4750          *           if name=="" then enumerates all printers
4751          *           if name!="" then enumerate the printer
4752          *          flags==PRINTER_ENUM_REMOTE
4753          *          name is NULL, enumerate printers
4754          * Level 2: name!="" enumerates printers, name can't be NULL
4755          * Level 3: doesn't exist
4756          * Level 4: does a local registry lookup
4757          * Level 5: same as Level 2
4758          */
4759
4760         if (r->in.server && r->in.server[0] == '\0') {
4761                 r->in.server = NULL;
4762         }
4763
4764         switch (r->in.level) {
4765         case 0:
4766                 result = enumprinters_level0(p->mem_ctx, session_info,
4767                                              p->msg_ctx, r->in.flags,
4768                                              r->in.server,
4769                                              r->out.info, r->out.count);
4770                 break;
4771         case 1:
4772                 result = enumprinters_level1(p->mem_ctx, session_info,
4773                                              p->msg_ctx, r->in.flags,
4774                                              r->in.server,
4775                                              r->out.info, r->out.count);
4776                 break;
4777         case 2:
4778                 result = enumprinters_level2(p->mem_ctx, session_info,
4779                                              p->msg_ctx, r->in.flags,
4780                                              r->in.server,
4781                                              r->out.info, r->out.count);
4782                 break;
4783         case 4:
4784                 result = enumprinters_level4(p->mem_ctx, session_info,
4785                                              p->msg_ctx, r->in.flags,
4786                                              r->in.server,
4787                                              r->out.info, r->out.count);
4788                 break;
4789         case 5:
4790                 result = enumprinters_level5(p->mem_ctx, session_info,
4791                                              p->msg_ctx, r->in.flags,
4792                                              r->in.server,
4793                                              r->out.info, r->out.count);
4794                 break;
4795         default:
4796                 return WERR_INVALID_LEVEL;
4797         }
4798
4799         if (!W_ERROR_IS_OK(result)) {
4800                 return result;
4801         }
4802
4803         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4804                                                      spoolss_EnumPrinters,
4805                                                      *r->out.info, r->in.level,
4806                                                      *r->out.count);
4807         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4808         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4809
4810         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4811 }
4812
4813 /****************************************************************
4814  _spoolss_GetPrinter
4815 ****************************************************************/
4816
4817 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4818                            struct spoolss_GetPrinter *r)
4819 {
4820         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4821         struct spoolss_PrinterInfo2 *info2 = NULL;
4822         WERROR result = WERR_OK;
4823         int snum;
4824
4825         /* that's an [in out] buffer */
4826
4827         if (!r->in.buffer && (r->in.offered != 0)) {
4828                 result = WERR_INVALID_PARAMETER;
4829                 goto err_info_free;
4830         }
4831
4832         *r->out.needed = 0;
4833
4834         if (Printer == NULL) {
4835                 result = WERR_INVALID_HANDLE;
4836                 goto err_info_free;
4837         }
4838
4839         if (Printer->printer_type == SPLHND_SERVER) {
4840
4841                 struct dcerpc_binding_handle *b;
4842
4843                 if (r->in.level != 3) {
4844                         result = WERR_INVALID_LEVEL;
4845                         goto err_info_free;
4846                 }
4847
4848                 result = winreg_printer_binding_handle(p->mem_ctx,
4849                                                        get_session_info_system(),
4850                                                        p->msg_ctx,
4851                                                        &b);
4852                 if (!W_ERROR_IS_OK(result)) {
4853                         goto err_info_free;
4854                 }
4855
4856                 result = winreg_get_printserver_secdesc(p->mem_ctx,
4857                                                         b,
4858                                                         &r->out.info->info3.secdesc);
4859                 if (!W_ERROR_IS_OK(result)) {
4860                         goto err_info_free;
4861                 }
4862
4863                 goto done;
4864         }
4865
4866         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4867                 result = WERR_INVALID_HANDLE;
4868                 goto err_info_free;
4869         }
4870
4871         result = winreg_get_printer_internal(p->mem_ctx,
4872                                     get_session_info_system(),
4873                                     p->msg_ctx,
4874                                     lp_const_servicename(snum),
4875                                     &info2);
4876         if (!W_ERROR_IS_OK(result)) {
4877                 goto err_info_free;
4878         }
4879
4880         switch (r->in.level) {
4881         case 0:
4882                 result = construct_printer_info0(p->mem_ctx,
4883                                                  get_session_info_system(),
4884                                                  p->msg_ctx,
4885                                                  info2,
4886                                                  Printer->servername,
4887                                                  &r->out.info->info0,
4888                                                  snum);
4889                 break;
4890         case 1:
4891                 result = construct_printer_info1(p->mem_ctx, info2,
4892                                                  PRINTER_ENUM_ICON8,
4893                                                  Printer->servername,
4894                                                  &r->out.info->info1, snum);
4895                 break;
4896         case 2:
4897                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4898                                                  Printer->servername,
4899                                                  &r->out.info->info2, snum);
4900                 break;
4901         case 3:
4902                 result = construct_printer_info3(p->mem_ctx, info2,
4903                                                  Printer->servername,
4904                                                  &r->out.info->info3, snum);
4905                 break;
4906         case 4:
4907                 result = construct_printer_info4(p->mem_ctx, info2,
4908                                                  Printer->servername,
4909                                                  &r->out.info->info4, snum);
4910                 break;
4911         case 5:
4912                 result = construct_printer_info5(p->mem_ctx, info2,
4913                                                  Printer->servername,
4914                                                  &r->out.info->info5, snum);
4915                 break;
4916         case 6:
4917                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4918                                                  Printer->servername,
4919                                                  &r->out.info->info6, snum);
4920                 break;
4921         case 7:
4922                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4923                                                  Printer->servername,
4924                                                  &r->out.info->info7, snum);
4925                 break;
4926         case 8:
4927                 result = construct_printer_info8(p->mem_ctx, info2,
4928                                                  Printer->servername,
4929                                                  &r->out.info->info8, snum);
4930                 break;
4931         default:
4932                 result = WERR_INVALID_LEVEL;
4933                 break;
4934         }
4935         TALLOC_FREE(info2);
4936
4937         if (!W_ERROR_IS_OK(result)) {
4938                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4939                           r->in.level, win_errstr(result)));
4940                 goto err_info_free;
4941         }
4942  done:
4943         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4944                                                r->out.info, r->in.level);
4945         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4946
4947         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4948
4949 err_info_free:
4950         TALLOC_FREE(r->out.info);
4951         return result;
4952 }
4953
4954 /********************************************************************
4955  ********************************************************************/
4956
4957 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4958         do { \
4959                 if (in && strlen(in)) { \
4960                         out = talloc_strdup(mem_ctx, in); \
4961                 } else { \
4962                         out = talloc_strdup(mem_ctx, ""); \
4963                 } \
4964                 W_ERROR_HAVE_NO_MEMORY(out); \
4965         } while (0);
4966
4967 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4968         do { \
4969                 if (in && strlen(in)) { \
4970                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4971                 } else { \
4972                         out = talloc_strdup(mem_ctx, ""); \
4973                 } \
4974                 W_ERROR_HAVE_NO_MEMORY(out); \
4975         } while (0);
4976
4977 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4978                                                   const char **string_array,
4979                                                   const char ***presult,
4980                                                   const char *cservername,
4981                                                   const char *arch,
4982                                                   int version)
4983 {
4984         int i;
4985         size_t num_strings = 0;
4986         const char **array = NULL;
4987
4988         if (string_array == NULL) {
4989                 return WERR_INVALID_PARAMETER;
4990         }
4991
4992         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4993                 const char *str = NULL;
4994
4995                 if (cservername == NULL || arch == NULL) {
4996                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4997                 } else {
4998                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4999                 }
5000
5001                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
5002                         TALLOC_FREE(array);
5003                         return WERR_NOT_ENOUGH_MEMORY;
5004                 }
5005         }
5006
5007         if (i > 0) {
5008                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
5009                              &array, &num_strings);
5010         }
5011
5012         if (presult != NULL) {
5013                 *presult = array;
5014         } else {
5015                 talloc_free(array);
5016         }
5017
5018         return WERR_OK;
5019 }
5020
5021 /********************************************************************
5022  * fill a spoolss_DriverInfo1 struct
5023  ********************************************************************/
5024
5025 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
5026                                         struct spoolss_DriverInfo1 *r,
5027                                         const struct spoolss_DriverInfo8 *driver,
5028                                         const char *servername)
5029 {
5030         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5031         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5032
5033         return WERR_OK;
5034 }
5035
5036 /********************************************************************
5037  * fill a spoolss_DriverInfo2 struct
5038  ********************************************************************/
5039
5040 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5041                                         struct spoolss_DriverInfo2 *r,
5042                                         const struct spoolss_DriverInfo8 *driver,
5043                                         const char *servername)
5044
5045 {
5046         const char *cservername = canon_servername(servername);
5047
5048         r->version              = driver->version;
5049
5050         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5051         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5052         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5053         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5054
5055         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5056                                driver->architecture,
5057                                driver->version,
5058                                driver->driver_path,
5059                                r->driver_path);
5060
5061         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5062                                driver->architecture,
5063                                driver->version,
5064                                driver->data_file,
5065                                r->data_file);
5066
5067         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5068                                driver->architecture,
5069                                driver->version,
5070                                driver->config_file,
5071                                r->config_file);
5072
5073         return WERR_OK;
5074 }
5075
5076 /********************************************************************
5077  * fill a spoolss_DriverInfo3 struct
5078  ********************************************************************/
5079
5080 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5081                                         struct spoolss_DriverInfo3 *r,
5082                                         const struct spoolss_DriverInfo8 *driver,
5083                                         const char *servername)
5084 {
5085         const char *cservername = canon_servername(servername);
5086
5087         r->version              = driver->version;
5088
5089         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5090         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5091         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5092         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5093
5094         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5095                                driver->architecture,
5096                                driver->version,
5097                                driver->driver_path,
5098                                r->driver_path);
5099
5100         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5101                                driver->architecture,
5102                                driver->version,
5103                                driver->data_file,
5104                                r->data_file);
5105
5106         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5107                                driver->architecture,
5108                                driver->version,
5109                                driver->config_file,
5110                                r->config_file);
5111
5112         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5113                                driver->architecture,
5114                                driver->version,
5115                                driver->help_file,
5116                                r->help_file);
5117
5118         FILL_DRIVER_STRING(mem_ctx,
5119                            driver->monitor_name,
5120                            r->monitor_name);
5121
5122         FILL_DRIVER_STRING(mem_ctx,
5123                            driver->default_datatype,
5124                            r->default_datatype);
5125
5126         return string_array_from_driver_info(mem_ctx,
5127                                              driver->dependent_files,
5128                                              &r->dependent_files,
5129                                              cservername,
5130                                              driver->architecture,
5131                                              driver->version);
5132 }
5133
5134 /********************************************************************
5135  * fill a spoolss_DriverInfo4 struct
5136  ********************************************************************/
5137
5138 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5139                                         struct spoolss_DriverInfo4 *r,
5140                                         const struct spoolss_DriverInfo8 *driver,
5141                                         const char *servername)
5142 {
5143         const char *cservername = canon_servername(servername);
5144         WERROR result;
5145
5146         r->version              = driver->version;
5147
5148         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5149         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5150         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5151         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5152
5153         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5154                                driver->architecture,
5155                                driver->version,
5156                                driver->driver_path,
5157                                r->driver_path);
5158
5159         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5160                                driver->architecture,
5161                                driver->version,
5162                                driver->data_file,
5163                                r->data_file);
5164
5165         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5166                                driver->architecture,
5167                                driver->version,
5168                                driver->config_file,
5169                                r->config_file);
5170
5171         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5172                                driver->architecture,
5173                                driver->version,
5174                                driver->help_file,
5175                                r->help_file);
5176
5177         result = string_array_from_driver_info(mem_ctx,
5178                                                driver->dependent_files,
5179                                                &r->dependent_files,
5180                                                cservername,
5181                                                driver->architecture,
5182                                                driver->version);
5183         if (!W_ERROR_IS_OK(result)) {
5184                 return result;
5185         }
5186
5187         FILL_DRIVER_STRING(mem_ctx,
5188                            driver->monitor_name,
5189                            r->monitor_name);
5190
5191         FILL_DRIVER_STRING(mem_ctx,
5192                            driver->default_datatype,
5193                            r->default_datatype);
5194
5195
5196         result = string_array_from_driver_info(mem_ctx,
5197                                                driver->previous_names,
5198                                                &r->previous_names,
5199                                                NULL, NULL, 0);
5200
5201         return result;
5202 }
5203
5204 /********************************************************************
5205  * fill a spoolss_DriverInfo5 struct
5206  ********************************************************************/
5207
5208 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5209                                         struct spoolss_DriverInfo5 *r,
5210                                         const struct spoolss_DriverInfo8 *driver,
5211                                         const char *servername)
5212 {
5213         const char *cservername = canon_servername(servername);
5214
5215         r->version              = driver->version;
5216
5217         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5218         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5219         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5220         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5221
5222         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5223                                driver->architecture,
5224                                driver->version,
5225                                driver->driver_path,
5226                                r->driver_path);
5227
5228         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5229                                driver->architecture,
5230                                driver->version,
5231                                driver->data_file,
5232                                r->data_file);
5233
5234         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5235                                driver->architecture,
5236                                driver->version,
5237                                driver->config_file,
5238                                r->config_file);
5239
5240         r->driver_attributes    = 0;
5241         r->config_version       = 0;
5242         r->driver_version       = 0;
5243
5244         return WERR_OK;
5245 }
5246 /********************************************************************
5247  * fill a spoolss_DriverInfo6 struct
5248  ********************************************************************/
5249
5250 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5251                                         struct spoolss_DriverInfo6 *r,
5252                                         const struct spoolss_DriverInfo8 *driver,
5253                                         const char *servername)
5254 {
5255         const char *cservername = canon_servername(servername);
5256         WERROR result;
5257
5258         r->version              = driver->version;
5259
5260         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5261         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5262         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5263         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5264
5265         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5266                                driver->architecture,
5267                                driver->version,
5268                                driver->driver_path,
5269                                r->driver_path);
5270
5271         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5272                                driver->architecture,
5273                                driver->version,
5274                                driver->data_file,
5275                                r->data_file);
5276
5277         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5278                                driver->architecture,
5279                                driver->version,
5280                                driver->config_file,
5281                                r->config_file);
5282
5283         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5284                                driver->architecture,
5285                                driver->version,
5286                                driver->help_file,
5287                                r->help_file);
5288
5289         FILL_DRIVER_STRING(mem_ctx,
5290                            driver->monitor_name,
5291                            r->monitor_name);
5292
5293         FILL_DRIVER_STRING(mem_ctx,
5294                            driver->default_datatype,
5295                            r->default_datatype);
5296
5297         result = string_array_from_driver_info(mem_ctx,
5298                                                driver->dependent_files,
5299                                                &r->dependent_files,
5300                                                cservername,
5301                                                driver->architecture,
5302                                                driver->version);
5303         if (!W_ERROR_IS_OK(result)) {
5304                 return result;
5305         }
5306
5307         result = string_array_from_driver_info(mem_ctx,
5308                                                driver->previous_names,
5309                                                &r->previous_names,
5310                                                NULL, NULL, 0);
5311         if (!W_ERROR_IS_OK(result)) {
5312                 return result;
5313         }
5314
5315         r->driver_date          = driver->driver_date;
5316         r->driver_version       = driver->driver_version;
5317
5318         FILL_DRIVER_STRING(mem_ctx,
5319                            driver->manufacturer_name,
5320                            r->manufacturer_name);
5321         FILL_DRIVER_STRING(mem_ctx,
5322                            driver->manufacturer_url,
5323                            r->manufacturer_url);
5324         FILL_DRIVER_STRING(mem_ctx,
5325                            driver->hardware_id,
5326                            r->hardware_id);
5327         FILL_DRIVER_STRING(mem_ctx,
5328                            driver->provider,
5329                            r->provider);
5330
5331         return WERR_OK;
5332 }
5333
5334 /********************************************************************
5335  * fill a spoolss_DriverInfo8 struct
5336  ********************************************************************/
5337
5338 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5339                                         struct spoolss_DriverInfo8 *r,
5340                                         const struct spoolss_DriverInfo8 *driver,
5341                                         const char *servername)
5342 {
5343         const char *cservername = canon_servername(servername);
5344         WERROR result;
5345
5346         r->version              = driver->version;
5347
5348         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5349         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5350         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5351         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5352
5353         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5354                                driver->architecture,
5355                                driver->version,
5356                                driver->driver_path,
5357                                r->driver_path);
5358
5359         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5360                                driver->architecture,
5361                                driver->version,
5362                                driver->data_file,
5363                                r->data_file);
5364
5365         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5366                                driver->architecture,
5367                                driver->version,
5368                                driver->config_file,
5369                                r->config_file);
5370
5371         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5372                                driver->architecture,
5373                                driver->version,
5374                                driver->help_file,
5375                                r->help_file);
5376
5377         FILL_DRIVER_STRING(mem_ctx,
5378                            driver->monitor_name,
5379                            r->monitor_name);
5380
5381         FILL_DRIVER_STRING(mem_ctx,
5382                            driver->default_datatype,
5383                            r->default_datatype);
5384
5385         result = string_array_from_driver_info(mem_ctx,
5386                                                driver->dependent_files,
5387                                                &r->dependent_files,
5388                                                cservername,
5389                                                driver->architecture,
5390                                                driver->version);
5391         if (!W_ERROR_IS_OK(result)) {
5392                 return result;
5393         }
5394
5395         result = string_array_from_driver_info(mem_ctx,
5396                                                driver->previous_names,
5397                                                &r->previous_names,
5398                                                NULL, NULL, 0);
5399         if (!W_ERROR_IS_OK(result)) {
5400                 return result;
5401         }
5402
5403         r->driver_date          = driver->driver_date;
5404         r->driver_version       = driver->driver_version;
5405
5406         FILL_DRIVER_STRING(mem_ctx,
5407                            driver->manufacturer_name,
5408                            r->manufacturer_name);
5409         FILL_DRIVER_STRING(mem_ctx,
5410                            driver->manufacturer_url,
5411                            r->manufacturer_url);
5412         FILL_DRIVER_STRING(mem_ctx,
5413                            driver->hardware_id,
5414                            r->hardware_id);
5415         FILL_DRIVER_STRING(mem_ctx,
5416                            driver->provider,
5417                            r->provider);
5418
5419         FILL_DRIVER_STRING(mem_ctx,
5420                            driver->print_processor,
5421                            r->print_processor);
5422         FILL_DRIVER_STRING(mem_ctx,
5423                            driver->vendor_setup,
5424                            r->vendor_setup);
5425
5426         result = string_array_from_driver_info(mem_ctx,
5427                                                driver->color_profiles,
5428                                                &r->color_profiles,
5429                                                NULL, NULL, 0);
5430         if (!W_ERROR_IS_OK(result)) {
5431                 return result;
5432         }
5433
5434         FILL_DRIVER_STRING(mem_ctx,
5435                            driver->inf_path,
5436                            r->inf_path);
5437
5438         r->printer_driver_attributes    = driver->printer_driver_attributes;
5439
5440         result = string_array_from_driver_info(mem_ctx,
5441                                                driver->core_driver_dependencies,
5442                                                &r->core_driver_dependencies,
5443                                                NULL, NULL, 0);
5444         if (!W_ERROR_IS_OK(result)) {
5445                 return result;
5446         }
5447
5448         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5449         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5450
5451         return WERR_OK;
5452 }
5453
5454 #if 0 /* disabled until marshalling issues are resolved - gd */
5455 /********************************************************************
5456  ********************************************************************/
5457
5458 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5459                                           struct spoolss_DriverFileInfo *r,
5460                                           const char *cservername,
5461                                           const char *file_name,
5462                                           enum spoolss_DriverFileType file_type,
5463                                           uint32_t file_version)
5464 {
5465         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5466                                           cservername, file_name);
5467         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5468         r->file_type    = file_type;
5469         r->file_version = file_version;
5470
5471         return WERR_OK;
5472 }
5473
5474 /********************************************************************
5475  ********************************************************************/
5476
5477 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5478                                                  const struct spoolss_DriverInfo8 *driver,
5479                                                  const char *cservername,
5480                                                  struct spoolss_DriverFileInfo **info_p,
5481                                                  uint32_t *count_p)
5482 {
5483         struct spoolss_DriverFileInfo *info = NULL;
5484         uint32_t count = 0;
5485         WERROR result;
5486         uint32_t i;
5487
5488         *info_p = NULL;
5489         *count_p = 0;
5490
5491         if (strlen(driver->driver_path)) {
5492                 info = talloc_realloc(mem_ctx, info,
5493                                             struct spoolss_DriverFileInfo,
5494                                             count + 1);
5495                 W_ERROR_HAVE_NO_MEMORY(info);
5496                 result = fill_spoolss_DriverFileInfo(info,
5497                                                      &info[count],
5498                                                      cservername,
5499                                                      driver->driver_path,
5500                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5501                                                      0);
5502                 W_ERROR_NOT_OK_RETURN(result);
5503                 count++;
5504         }
5505
5506         if (strlen(driver->config_file)) {
5507                 info = talloc_realloc(mem_ctx, info,
5508                                             struct spoolss_DriverFileInfo,
5509                                             count + 1);
5510                 W_ERROR_HAVE_NO_MEMORY(info);
5511                 result = fill_spoolss_DriverFileInfo(info,
5512                                                      &info[count],
5513                                                      cservername,
5514                                                      driver->config_file,
5515                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5516                                                      0);
5517                 W_ERROR_NOT_OK_RETURN(result);
5518                 count++;
5519         }
5520
5521         if (strlen(driver->data_file)) {
5522                 info = talloc_realloc(mem_ctx, info,
5523                                             struct spoolss_DriverFileInfo,
5524                                             count + 1);
5525                 W_ERROR_HAVE_NO_MEMORY(info);
5526                 result = fill_spoolss_DriverFileInfo(info,
5527                                                      &info[count],
5528                                                      cservername,
5529                                                      driver->data_file,
5530                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5531                                                      0);
5532                 W_ERROR_NOT_OK_RETURN(result);
5533                 count++;
5534         }
5535
5536         if (strlen(driver->help_file)) {
5537                 info = talloc_realloc(mem_ctx, info,
5538                                             struct spoolss_DriverFileInfo,
5539                                             count + 1);
5540                 W_ERROR_HAVE_NO_MEMORY(info);
5541                 result = fill_spoolss_DriverFileInfo(info,
5542                                                      &info[count],
5543                                                      cservername,
5544                                                      driver->help_file,
5545                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5546                                                      0);
5547                 W_ERROR_NOT_OK_RETURN(result);
5548                 count++;
5549         }
5550
5551         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5552                 info = talloc_realloc(mem_ctx, info,
5553                                             struct spoolss_DriverFileInfo,
5554                                             count + 1);
5555                 W_ERROR_HAVE_NO_MEMORY(info);
5556                 result = fill_spoolss_DriverFileInfo(info,
5557                                                      &info[count],
5558                                                      cservername,
5559                                                      driver->dependent_files[i],
5560                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5561                                                      0);
5562                 W_ERROR_NOT_OK_RETURN(result);
5563                 count++;
5564         }
5565
5566         *info_p = info;
5567         *count_p = count;
5568
5569         return WERR_OK;
5570 }
5571
5572 /********************************************************************
5573  * fill a spoolss_DriverInfo101 struct
5574  ********************************************************************/
5575
5576 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5577                                           struct spoolss_DriverInfo101 *r,
5578                                           const struct spoolss_DriverInfo8 *driver,
5579                                           const char *servername)
5580 {
5581         const char *cservername = canon_servername(servername);
5582         WERROR result;
5583
5584         r->version              = driver->version;
5585
5586         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5587         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5588         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5589         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5590
5591         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5592                                                     cservername,
5593                                                     &r->file_info,
5594                                                     &r->file_count);
5595         if (!W_ERROR_IS_OK(result)) {
5596                 return result;
5597         }
5598
5599         FILL_DRIVER_STRING(mem_ctx,
5600                            driver->monitor_name,
5601                            r->monitor_name);
5602
5603         FILL_DRIVER_STRING(mem_ctx,
5604                            driver->default_datatype,
5605                            r->default_datatype);
5606
5607         result = string_array_from_driver_info(mem_ctx,
5608                                                driver->previous_names,
5609                                                &r->previous_names,
5610                                                NULL, NULL, 0);
5611         if (!W_ERROR_IS_OK(result)) {
5612                 return result;
5613         }
5614
5615         r->driver_date          = driver->driver_date;
5616         r->driver_version       = driver->driver_version;
5617
5618         FILL_DRIVER_STRING(mem_ctx,
5619                            driver->manufacturer_name,
5620                            r->manufacturer_name);
5621         FILL_DRIVER_STRING(mem_ctx,
5622                            driver->manufacturer_url,
5623                            r->manufacturer_url);
5624         FILL_DRIVER_STRING(mem_ctx,
5625                            driver->hardware_id,
5626                            r->hardware_id);
5627         FILL_DRIVER_STRING(mem_ctx,
5628                            driver->provider,
5629                            r->provider);
5630
5631         return WERR_OK;
5632 }
5633 #endif
5634 /********************************************************************
5635  ********************************************************************/
5636
5637 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5638                                                   const struct auth_session_info *session_info,
5639                                                   struct messaging_context *msg_ctx,
5640                                                   uint32_t level,
5641                                                   union spoolss_DriverInfo *r,
5642                                                   int snum,
5643                                                   const char *servername,
5644                                                   const char *architecture,
5645                                                   uint32_t version)
5646 {
5647         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5648         struct spoolss_DriverInfo8 *driver;
5649         WERROR result;
5650         struct dcerpc_binding_handle *b;
5651         TALLOC_CTX *tmp_ctx = NULL;
5652
5653         if (level == 101) {
5654                 return WERR_INVALID_LEVEL;
5655         }
5656
5657         tmp_ctx = talloc_new(mem_ctx);
5658         if (!tmp_ctx) {
5659                 return WERR_NOT_ENOUGH_MEMORY;
5660         }
5661
5662         result = winreg_printer_binding_handle(tmp_ctx,
5663                                                session_info,
5664                                                msg_ctx,
5665                                                &b);
5666         if (!W_ERROR_IS_OK(result)) {
5667                 goto done;
5668         }
5669
5670         result = winreg_get_printer(tmp_ctx, b,
5671                                     lp_const_servicename(snum),
5672                                     &pinfo2);
5673         if (!W_ERROR_IS_OK(result)) {
5674                 DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
5675                         lp_const_servicename(snum), win_errstr(result));
5676                 result = WERR_INVALID_PRINTER_NAME;
5677                 goto done;
5678         }
5679
5680         if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
5681                 return WERR_UNKNOWN_PRINTER_DRIVER;
5682         }
5683
5684         DBG_INFO("Construct printer driver [%s] for [%s]\n",
5685                  pinfo2->drivername,
5686                  pinfo2->sharename);
5687
5688         result = winreg_get_driver(tmp_ctx, b,
5689                                    architecture,
5690                                    pinfo2->drivername, version, &driver);
5691
5692         DBG_INFO("winreg_get_driver() status: %s\n",
5693                  win_errstr(result));
5694
5695         if (!W_ERROR_IS_OK(result)) {
5696                 /*
5697                  * Is this a W2k client ?
5698                  */
5699
5700                 if (version < 3) {
5701                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5702                         goto done;
5703                 }
5704
5705                 /* Yes - try again with a WinNT driver. */
5706                 version = 2;
5707                 result = winreg_get_driver(tmp_ctx, b,
5708                                            architecture,
5709                                            pinfo2->drivername,
5710                                            version, &driver);
5711                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5712                         win_errstr(result)));
5713                 if (!W_ERROR_IS_OK(result)) {
5714                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5715                         goto done;
5716                 }
5717         }
5718
5719         /* these are allocated on mem_ctx and not tmp_ctx because they are
5720          * the 'return value' and need to utlive this call */
5721         switch (level) {
5722         case 1:
5723                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5724                 break;
5725         case 2:
5726                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5727                 break;
5728         case 3:
5729                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5730                 break;
5731         case 4:
5732                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5733                 break;
5734         case 5:
5735                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5736                 break;
5737         case 6:
5738                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5739                 break;
5740         case 8:
5741                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5742                 break;
5743 #if 0 /* disabled until marshalling issues are resolved - gd */
5744         case 101:
5745                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5746                 break;
5747 #endif
5748         default:
5749                 result = WERR_INVALID_LEVEL;
5750                 break;
5751         }
5752
5753 done:
5754         talloc_free(tmp_ctx);
5755         return result;
5756 }
5757
5758 /****************************************************************
5759  _spoolss_GetPrinterDriver2
5760 ****************************************************************/
5761
5762 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5763                                   struct spoolss_GetPrinterDriver2 *r)
5764 {
5765         struct printer_handle *printer;
5766         WERROR result;
5767         uint32_t version = r->in.client_major_version;
5768
5769         int snum;
5770
5771         /* that's an [in out] buffer */
5772
5773         if (!r->in.buffer && (r->in.offered != 0)) {
5774                 result = WERR_INVALID_PARAMETER;
5775                 goto err_info_free;
5776         }
5777
5778         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5779
5780         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5781                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5782                 result = WERR_INVALID_PRINTER_NAME;
5783                 goto err_info_free;
5784         }
5785
5786         *r->out.needed = 0;
5787         *r->out.server_major_version = 0;
5788         *r->out.server_minor_version = 0;
5789
5790         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5791                 result = WERR_INVALID_HANDLE;
5792                 goto err_info_free;
5793         }
5794
5795         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5796                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5797                         "downgrading to v3\n"));
5798                 version = SPOOLSS_DRIVER_VERSION_200X;
5799         }
5800
5801         result = construct_printer_driver_info_level(p->mem_ctx,
5802                                                      get_session_info_system(),
5803                                                      p->msg_ctx,
5804                                                      r->in.level, r->out.info,
5805                                                      snum, printer->servername,
5806                                                      r->in.architecture,
5807                                                      version);
5808         if (!W_ERROR_IS_OK(result)) {
5809                 goto err_info_free;
5810         }
5811
5812         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5813                                                r->out.info, r->in.level);
5814         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5815
5816         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5817
5818 err_info_free:
5819         TALLOC_FREE(r->out.info);
5820         return result;
5821 }
5822
5823
5824 /****************************************************************
5825  _spoolss_StartPagePrinter
5826 ****************************************************************/
5827
5828 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5829                                  struct spoolss_StartPagePrinter *r)
5830 {
5831         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5832
5833         if (!Printer) {
5834                 DEBUG(3,("_spoolss_StartPagePrinter: "
5835                         "Error in startpageprinter printer handle\n"));
5836                 return WERR_INVALID_HANDLE;
5837         }
5838
5839         Printer->page_started = true;
5840         return WERR_OK;
5841 }
5842
5843 /****************************************************************
5844  _spoolss_EndPagePrinter
5845 ****************************************************************/
5846
5847 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5848                                struct spoolss_EndPagePrinter *r)
5849 {
5850         int snum;
5851
5852         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5853
5854         if (!Printer) {
5855                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5856                         OUR_HANDLE(r->in.handle)));
5857                 return WERR_INVALID_HANDLE;
5858         }
5859
5860         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5861                 return WERR_INVALID_HANDLE;
5862
5863         Printer->page_started = false;
5864         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5865
5866         return WERR_OK;
5867 }
5868
5869 /****************************************************************
5870  _spoolss_StartDocPrinter
5871 ****************************************************************/
5872
5873 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5874                                 struct spoolss_StartDocPrinter *r)
5875 {
5876         struct spoolss_DocumentInfo1 *info_1;
5877         int snum;
5878         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5879         WERROR werr;
5880         char *rhost;
5881         int rc;
5882
5883         if (!Printer) {
5884                 DEBUG(2,("_spoolss_StartDocPrinter: "
5885                         "Invalid handle (%s:%u:%u)\n",
5886                         OUR_HANDLE(r->in.handle)));
5887                 return WERR_INVALID_HANDLE;
5888         }
5889
5890         if (Printer->jobid) {
5891                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5892                           "StartDocPrinter called twice! "
5893                           "(existing jobid = %d)\n", Printer->jobid));
5894                 return WERR_INVALID_HANDLE;
5895         }
5896
5897         if (r->in.info_ctr->level != 1) {
5898                 return WERR_INVALID_LEVEL;
5899         }
5900
5901         info_1 = r->in.info_ctr->info.info1;
5902
5903         /*
5904          * a nice thing with NT is it doesn't listen to what you tell it.
5905          * when asked to send _only_ RAW datas, it tries to send datas
5906          * in EMF format.
5907          *
5908          * So I add checks like in NT Server ...
5909          */
5910
5911         if (info_1->datatype) {
5912                 /*
5913                  * The v4 driver model used in Windows 8 declares print jobs
5914                  * intended to bypass the XPS processing layer by setting
5915                  * datatype to "XPS_PASS" instead of "RAW".
5916                  */
5917                 if ((strcmp(info_1->datatype, "RAW") != 0)
5918                  && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5919                         *r->out.job_id = 0;
5920                         return WERR_INVALID_DATATYPE;
5921                 }
5922         }
5923
5924         /* get the share number of the printer */
5925         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5926                 return WERR_INVALID_HANDLE;
5927         }
5928
5929         rc = get_remote_hostname(p->remote_address,
5930                                  &rhost,
5931                                  p->mem_ctx);
5932         if (rc < 0) {
5933                 return WERR_NOT_ENOUGH_MEMORY;
5934         }
5935         if (strequal(rhost,"UNKNOWN")) {
5936                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5937                                                          p->mem_ctx);
5938                 if (rhost == NULL) {
5939                         return WERR_NOT_ENOUGH_MEMORY;
5940                 }
5941         }
5942
5943         werr = print_job_start(p->session_info,
5944                                p->msg_ctx,
5945                                rhost,
5946                                snum,
5947                                info_1->document_name,
5948                                info_1->output_file,
5949                                Printer->devmode,
5950                                &Printer->jobid);
5951
5952         /* An error occured in print_job_start() so return an appropriate
5953            NT error code. */
5954
5955         if (!W_ERROR_IS_OK(werr)) {
5956                 return werr;
5957         }
5958
5959         Printer->document_started = true;
5960         *r->out.job_id = Printer->jobid;
5961
5962         return WERR_OK;
5963 }
5964
5965 /****************************************************************
5966  _spoolss_EndDocPrinter
5967 ****************************************************************/
5968
5969 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5970                               struct spoolss_EndDocPrinter *r)
5971 {
5972         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5973         NTSTATUS status;
5974         int snum;
5975
5976         if (!Printer) {
5977                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5978                         OUR_HANDLE(r->in.handle)));
5979                 return WERR_INVALID_HANDLE;
5980         }
5981
5982         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5983                 return WERR_INVALID_HANDLE;
5984         }
5985
5986         Printer->document_started = false;
5987         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5988         if (!NT_STATUS_IS_OK(status)) {
5989                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5990                           "print_job_end failed [%s]\n",
5991                           nt_errstr(status)));
5992         }
5993
5994         Printer->jobid = 0;
5995         return ntstatus_to_werror(status);
5996 }
5997
5998 /****************************************************************
5999  _spoolss_WritePrinter
6000 ****************************************************************/
6001
6002 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
6003                              struct spoolss_WritePrinter *r)
6004 {
6005         ssize_t buffer_written;
6006         int snum;
6007         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6008
6009         if (!Printer) {
6010                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
6011                         OUR_HANDLE(r->in.handle)));
6012                 *r->out.num_written = r->in._data_size;
6013                 return WERR_INVALID_HANDLE;
6014         }
6015
6016         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6017                 return WERR_INVALID_HANDLE;
6018
6019         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
6020         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
6021                                                    snum, Printer->jobid,
6022                                                    (const char *)r->in.data.data,
6023                                                    (size_t)r->in._data_size);
6024         if (buffer_written == (ssize_t)-1) {
6025                 *r->out.num_written = 0;
6026                 if (errno == ENOSPC)
6027                         return WERR_NO_SPOOL_SPACE;
6028                 else
6029                         return WERR_ACCESS_DENIED;
6030         }
6031
6032         *r->out.num_written = r->in._data_size;
6033
6034         return WERR_OK;
6035 }
6036
6037 /********************************************************************
6038  * api_spoolss_getprinter
6039  * called from the spoolss dispatcher
6040  *
6041  ********************************************************************/
6042
6043 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
6044                               struct pipes_struct *p)
6045 {
6046         const struct auth_session_info *session_info = p->session_info;
6047         int snum;
6048         WERROR errcode = WERR_INVALID_FUNCTION;
6049         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6050
6051         if (!Printer) {
6052                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
6053                         OUR_HANDLE(handle)));
6054                 return WERR_INVALID_HANDLE;
6055         }
6056
6057         if (!get_printer_snum(p, handle, &snum, NULL))
6058                 return WERR_INVALID_HANDLE;
6059
6060         switch (command) {
6061         case SPOOLSS_PRINTER_CONTROL_PAUSE:
6062                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
6063                 break;
6064         case SPOOLSS_PRINTER_CONTROL_RESUME:
6065         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6066                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6067                 break;
6068         case SPOOLSS_PRINTER_CONTROL_PURGE:
6069                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6070                 break;
6071         default:
6072                 return WERR_INVALID_LEVEL;
6073         }
6074
6075         return errcode;
6076 }
6077
6078
6079 /****************************************************************
6080  _spoolss_AbortPrinter
6081  * From MSDN: "Deletes printer's spool file if printer is configured
6082  * for spooling"
6083 ****************************************************************/
6084
6085 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6086                              struct spoolss_AbortPrinter *r)
6087 {
6088         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
6089         int             snum;
6090         WERROR          errcode = WERR_OK;
6091
6092         if (!Printer) {
6093                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6094                         OUR_HANDLE(r->in.handle)));
6095                 return WERR_INVALID_HANDLE;
6096         }
6097
6098         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6099                 return WERR_INVALID_HANDLE;
6100
6101         if (!Printer->document_started) {
6102                 return WERR_SPL_NO_STARTDOC;
6103         }
6104
6105         errcode = print_job_delete(p->session_info,
6106                                    p->msg_ctx,
6107                                    snum,
6108                                    Printer->jobid);
6109
6110         return errcode;
6111 }
6112
6113 /********************************************************************
6114  * called by spoolss_api_setprinter
6115  * when updating a printer description
6116  ********************************************************************/
6117
6118 static WERROR update_printer_sec(struct policy_handle *handle,
6119                                  struct pipes_struct *p,
6120                                  struct sec_desc_buf *secdesc_ctr)
6121 {
6122         struct spoolss_security_descriptor *new_secdesc = NULL;
6123         struct spoolss_security_descriptor *old_secdesc = NULL;
6124         const char *printer = NULL;
6125         WERROR result;
6126         int snum = -1;
6127         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6128         struct dcerpc_binding_handle *b;
6129         TALLOC_CTX *tmp_ctx = NULL;
6130         bool ok = false;
6131
6132         if (!Printer) {
6133                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6134                          OUR_HANDLE(handle)));
6135
6136                 result = WERR_INVALID_HANDLE;
6137                 goto done;
6138         }
6139
6140         if (secdesc_ctr == NULL) {
6141                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6142                 result = WERR_INVALID_PARAMETER;
6143                 goto done;
6144         }
6145
6146         switch (Printer->printer_type) {
6147         case SPLHND_SERVER:
6148                 break;
6149         case SPLHND_PRINTER:
6150                 if (!get_printer_snum(p, handle, &snum, NULL)) {
6151                         DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6152                                  OUR_HANDLE(handle)));
6153                         result = WERR_INVALID_HANDLE;
6154                         goto done;
6155                 }
6156                 printer = lp_const_servicename(snum);
6157                 break;
6158         default:
6159                 break;
6160         }
6161
6162         /* Check the user has permissions to change the security
6163            descriptor.  By experimentation with two NT machines, the user
6164            requires Full Access to the printer to change security
6165            information. */
6166
6167         switch (Printer->printer_type) {
6168         case SPLHND_SERVER:
6169                 ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
6170                 break;
6171         case SPLHND_PRINTER:
6172                 ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
6173                 break;
6174         default:
6175                 break;
6176         }
6177
6178         if (!ok) {
6179                 DEBUG(4,("update_printer_sec: updated denied by printer permissions "
6180                         "(access_granted: 0x%08x)\n", Printer->access_granted));
6181                 result = WERR_ACCESS_DENIED;
6182                 goto done;
6183         }
6184
6185         tmp_ctx = talloc_new(p->mem_ctx);
6186         if (!tmp_ctx) {
6187                 return WERR_NOT_ENOUGH_MEMORY;
6188         }
6189
6190         result = winreg_printer_binding_handle(tmp_ctx,
6191                                                get_session_info_system(),
6192                                                p->msg_ctx,
6193                                                &b);
6194         if (!W_ERROR_IS_OK(result)) {
6195                 goto done;
6196         }
6197
6198         /* NT seems to like setting the security descriptor even though
6199            nothing may have actually changed. */
6200
6201         if (printer != NULL) {
6202                 result = winreg_get_printer_secdesc(tmp_ctx, b,
6203                                                     printer,
6204                                                     &old_secdesc);
6205         } else {
6206                 result = winreg_get_printserver_secdesc(tmp_ctx, b,
6207                                                         &old_secdesc);
6208         }
6209         if (!W_ERROR_IS_OK(result)) {
6210                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6211                 result = WERR_INVALID_HANDLE;
6212                 goto done;
6213         }
6214
6215         if (DEBUGLEVEL >= 10) {
6216                 struct security_acl *the_acl;
6217                 int i;
6218
6219                 the_acl = old_secdesc->dacl;
6220                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6221                            printer, the_acl->num_aces));
6222
6223                 for (i = 0; i < the_acl->num_aces; i++) {
6224                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6225                                            &the_acl->aces[i].trustee),
6226                                   the_acl->aces[i].access_mask));
6227                 }
6228
6229                 the_acl = secdesc_ctr->sd->dacl;
6230
6231                 if (the_acl) {
6232                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6233                                    printer, the_acl->num_aces));
6234
6235                         for (i = 0; i < the_acl->num_aces; i++) {
6236                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6237                                                    &the_acl->aces[i].trustee),
6238                                            the_acl->aces[i].access_mask));
6239                         }
6240                 } else {
6241                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6242                 }
6243         }
6244
6245         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6246         if (new_secdesc == NULL) {
6247                 result = WERR_NOT_ENOUGH_MEMORY;
6248                 goto done;
6249         }
6250
6251         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6252                 result = WERR_OK;
6253                 goto done;
6254         }
6255
6256         if (printer != NULL) {
6257                 result = winreg_set_printer_secdesc(tmp_ctx, b,
6258                                                     printer,
6259                                                     new_secdesc);
6260         } else {
6261                 result = winreg_set_printserver_secdesc(tmp_ctx, b,
6262                                                         new_secdesc);
6263         }
6264
6265 done:
6266         talloc_free(tmp_ctx);
6267         return result;
6268 }
6269
6270 /********************************************************************
6271  Canonicalize printer info from a client
6272  ********************************************************************/
6273
6274 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6275                              struct spoolss_SetPrinterInfo2 *info2,
6276                              int snum)
6277 {
6278         fstring printername;
6279         const char *p;
6280
6281         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6282                 "portname=%s drivername=%s comment=%s location=%s\n",
6283                 info2->servername, info2->printername, info2->sharename,
6284                 info2->portname, info2->drivername, info2->comment,
6285                 info2->location));
6286
6287         /* we force some elements to "correct" values */
6288         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6289         if (info2->servername == NULL) {
6290                 return false;
6291         }
6292         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6293         if (info2->sharename == NULL) {
6294                 return false;
6295         }
6296
6297         /* check to see if we allow printername != sharename */
6298         if (lp_force_printername(snum)) {
6299                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6300                                         lp_netbios_name(), info2->sharename);
6301         } else {
6302                 /* make sure printername is in \\server\printername format */
6303                 fstrcpy(printername, info2->printername);
6304                 p = printername;
6305                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6306                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6307                                 p++;
6308                 }
6309
6310                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6311                                         lp_netbios_name(), p);
6312         }
6313         if (info2->printername == NULL) {
6314                 return false;
6315         }
6316
6317         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6318         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6319
6320         return true;
6321 }
6322
6323 /****************************************************************************
6324 ****************************************************************************/
6325
6326 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6327 {
6328         char *cmd = lp_addport_command(talloc_tos());
6329         char *command = NULL;
6330         int ret;
6331         bool is_print_op = false;
6332
6333         if ( !*cmd ) {
6334                 return WERR_ACCESS_DENIED;
6335         }
6336
6337         command = talloc_asprintf(ctx,
6338                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6339         if (!command) {
6340                 return WERR_NOT_ENOUGH_MEMORY;
6341         }
6342
6343         if ( token )
6344                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6345
6346         DEBUG(10,("Running [%s]\n", command));
6347
6348         /********* BEGIN SePrintOperatorPrivilege **********/
6349
6350         if ( is_print_op )
6351                 become_root();
6352
6353         ret = smbrun(command, NULL, NULL);
6354
6355         if ( is_print_op )
6356                 unbecome_root();
6357
6358         /********* END SePrintOperatorPrivilege **********/
6359
6360         DEBUGADD(10,("returned [%d]\n", ret));
6361
6362         TALLOC_FREE(command);
6363
6364         if ( ret != 0 ) {
6365                 return WERR_ACCESS_DENIED;
6366         }
6367
6368         return WERR_OK;
6369 }
6370
6371 /****************************************************************************
6372 ****************************************************************************/
6373
6374 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6375                                    int snum)
6376 {
6377         /*
6378          * As we do not know if we are embedded in the file server process
6379          * or not, we have to pretend that all shares are in use.
6380          */
6381         return true;
6382 }
6383
6384 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6385                              struct spoolss_SetPrinterInfo2 *info2,
6386                              const char *remote_machine,
6387                              struct messaging_context *msg_ctx)
6388 {
6389         char *cmd = lp_addprinter_command(talloc_tos());
6390         char **qlines;
6391         char *command = NULL;
6392         int numlines;
6393         int ret;
6394         int fd;
6395         bool is_print_op = false;
6396
6397         if (!remote_machine) {
6398                 return false;
6399         }
6400
6401         command = talloc_asprintf(ctx,
6402                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6403                         cmd, info2->printername, info2->sharename,
6404                         info2->portname, info2->drivername,
6405                         info2->location, info2->comment, remote_machine);
6406         if (!command) {
6407                 return false;
6408         }
6409
6410         if ( token )
6411                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6412
6413         DEBUG(10,("Running [%s]\n", command));
6414
6415         /********* BEGIN SePrintOperatorPrivilege **********/
6416
6417         if ( is_print_op )
6418                 become_root();
6419
6420         ret = smbrun(command, &fd, NULL);
6421         if (ret == 0) {
6422                 /* Tell everyone we updated smb.conf. */
6423                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6424         }
6425
6426         if ( is_print_op )
6427                 unbecome_root();
6428
6429         /********* END SePrintOperatorPrivilege **********/
6430
6431         DEBUGADD(10,("returned [%d]\n", ret));
6432
6433         TALLOC_FREE(command);
6434
6435         if ( ret != 0 ) {
6436                 if (fd != -1)
6437                         close(fd);
6438                 return false;
6439         }
6440
6441         /* reload our services immediately */
6442         become_root();
6443         reload_services(NULL, spoolss_conn_snum_used, false);
6444         unbecome_root();
6445
6446         numlines = 0;
6447         /* Get lines and convert them back to dos-codepage */
6448         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6449         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6450         close(fd);
6451
6452         /* Set the portname to what the script says the portname should be. */
6453         /* but don't require anything to be return from the script exit a good error code */
6454
6455         if (numlines) {
6456                 /* Set the portname to what the script says the portname should be. */
6457                 info2->portname = talloc_strdup(ctx, qlines[0]);
6458                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6459         }
6460
6461         TALLOC_FREE(qlines);
6462         return true;
6463 }
6464
6465 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6466                                const struct auth_session_info *session_info,
6467                                struct messaging_context *msg_ctx,
6468                                int snum,
6469                                struct spoolss_SetPrinterInfo2 *printer,
6470                                struct spoolss_PrinterInfo2 *old_printer)
6471 {
6472         bool force_update = (old_printer == NULL);
6473         const char *dnsdomname;
6474         const char *longname;
6475         const char *uncname;
6476         const char *spooling;
6477         DATA_BLOB buffer;
6478         WERROR result = WERR_OK;
6479         struct dcerpc_binding_handle *b;
6480         TALLOC_CTX *tmp_ctx;
6481         bool ok;
6482
6483         tmp_ctx = talloc_new(mem_ctx);
6484         if (!tmp_ctx) {
6485                 return WERR_NOT_ENOUGH_MEMORY;
6486         }
6487
6488         result = winreg_printer_binding_handle(tmp_ctx,
6489                                                session_info,
6490                                                msg_ctx,
6491                                                &b);
6492         if (!W_ERROR_IS_OK(result)) {
6493                 goto done;
6494         }
6495
6496         if (printer->drivername != NULL &&
6497             (force_update ||
6498              !strequal(printer->drivername, old_printer->drivername))) {
6499                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6500                 if (!ok) {
6501                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6502                         result = WERR_INVALID_DATA;
6503                         goto done;
6504                 }
6505                 result = winreg_set_printer_dataex(tmp_ctx, b,
6506                                           printer->sharename,
6507                                           SPOOL_DSSPOOLER_KEY,
6508                                           SPOOL_REG_DRIVERNAME,
6509                                           REG_SZ,
6510                                           buffer.data,
6511                                           buffer.length);
6512                 if (!W_ERROR_IS_OK(result)) {
6513                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6514                         goto done;
6515                 }
6516
6517                 if (!force_update) {
6518                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6519                                 printer->drivername));
6520
6521                         notify_printer_driver(server_event_context(), msg_ctx,
6522                                               snum, printer->drivername ?
6523                                               printer->drivername : "");
6524                 }
6525         }
6526
6527         if (printer->comment != NULL &&
6528             (force_update ||
6529              !strequal(printer->comment, old_printer->comment))) {
6530                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6531                 if (!ok) {
6532                         DEBUG(0, ("comment data corrupted\n"));
6533                         result = WERR_INVALID_DATA;
6534                         goto done;
6535                 }
6536                 result = winreg_set_printer_dataex(tmp_ctx, b,
6537                                           printer->sharename,
6538                                           SPOOL_DSSPOOLER_KEY,
6539                                           SPOOL_REG_DESCRIPTION,
6540                                           REG_SZ,
6541                                           buffer.data,
6542                                           buffer.length);
6543                 if (!W_ERROR_IS_OK(result)) {
6544                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6545                         goto done;
6546                 }
6547
6548                 if (!force_update) {
6549                         notify_printer_comment(server_event_context(), msg_ctx,
6550                                                snum, printer->comment ?
6551                                                printer->comment : "");
6552                 }
6553         }
6554
6555         if (printer->sharename != NULL &&
6556             (force_update ||
6557              !strequal(printer->sharename, old_printer->sharename))) {
6558                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6559                 if (!ok) {
6560                         DEBUG(0, ("sharename data corrupted\n"));
6561                         result = WERR_INVALID_DATA;
6562                         goto done;
6563                 }
6564                 result = winreg_set_printer_dataex(tmp_ctx, b,
6565                                           printer->sharename,
6566                                           SPOOL_DSSPOOLER_KEY,
6567                                           SPOOL_REG_PRINTSHARENAME,
6568                                           REG_SZ,
6569                                           buffer.data,
6570                                           buffer.length);
6571                 if (!W_ERROR_IS_OK(result)) {
6572                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6573                         goto done;
6574                 }
6575
6576                 if (!force_update) {
6577                         notify_printer_sharename(server_event_context(),
6578                                                  msg_ctx,
6579                                                  snum, printer->sharename ?
6580                                                  printer->sharename : "");
6581                 }
6582
6583                 /* name change, purge any cache entries for the old */
6584                 prune_printername_cache();
6585         }
6586
6587         if (printer->printername != NULL &&
6588             (force_update ||
6589              !strequal(printer->printername, old_printer->printername))) {
6590                 const char *p;
6591
6592                 p = strrchr(printer->printername, '\\' );
6593                 if (p != NULL) {
6594                         p++;
6595                 } else {
6596                         p = printer->printername;
6597                 }
6598
6599                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6600                 if (!ok) {
6601                         DEBUG(0, ("printername data corrupted\n"));
6602                         result = WERR_INVALID_DATA;
6603                         goto done;
6604                 }
6605                 result = winreg_set_printer_dataex(tmp_ctx, b,
6606                                           printer->sharename,
6607                                           SPOOL_DSSPOOLER_KEY,
6608                                           SPOOL_REG_PRINTERNAME,
6609                                           REG_SZ,
6610                                           buffer.data,
6611                                           buffer.length);
6612                 if (!W_ERROR_IS_OK(result)) {
6613                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6614                         goto done;
6615                 }
6616
6617                 if (!force_update) {
6618                         notify_printer_printername(server_event_context(),
6619                                                    msg_ctx, snum, p ? p : "");
6620                 }
6621
6622                 /* name change, purge any cache entries for the old */
6623                 prune_printername_cache();
6624         }
6625
6626         if (printer->portname != NULL &&
6627             (force_update ||
6628              !strequal(printer->portname, old_printer->portname))) {
6629                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6630                 if (!ok) {
6631                         DEBUG(0, ("portname data corrupted\n"));
6632                         result = WERR_INVALID_DATA;
6633                         goto done;
6634                 }
6635                 result = winreg_set_printer_dataex(tmp_ctx, b,
6636                                           printer->sharename,
6637                                           SPOOL_DSSPOOLER_KEY,
6638                                           SPOOL_REG_PORTNAME,
6639                                           REG_SZ,
6640                                           buffer.data,
6641                                           buffer.length);
6642                 if (!W_ERROR_IS_OK(result)) {
6643                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6644                         goto done;
6645                 }
6646
6647                 if (!force_update) {
6648                         notify_printer_port(server_event_context(),
6649                                             msg_ctx, snum, printer->portname ?
6650                                             printer->portname : "");
6651                 }
6652         }
6653
6654         if (printer->location != NULL &&
6655             (force_update ||
6656              !strequal(printer->location, old_printer->location))) {
6657                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6658                 if (!ok) {
6659                         DEBUG(0, ("location data corrupted\n"));
6660                         result = WERR_INVALID_DATA;
6661                         goto done;
6662                 }
6663                 result = winreg_set_printer_dataex(tmp_ctx, b,
6664                                           printer->sharename,
6665                                           SPOOL_DSSPOOLER_KEY,
6666                                           SPOOL_REG_LOCATION,
6667                                           REG_SZ,
6668                                           buffer.data,
6669                                           buffer.length);
6670                 if (!W_ERROR_IS_OK(result)) {
6671                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6672                         goto done;
6673                 }
6674
6675                 if (!force_update) {
6676                         notify_printer_location(server_event_context(),
6677                                                 msg_ctx, snum,
6678                                                 printer->location ?
6679                                                 printer->location : "");
6680                 }
6681         }
6682
6683         if (printer->sepfile != NULL &&
6684             (force_update ||
6685              !strequal(printer->sepfile, old_printer->sepfile))) {
6686                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6687                 if (!ok) {
6688                         DEBUG(0, ("sepfile data corrupted\n"));
6689                         result = WERR_INVALID_DATA;
6690                         goto done;
6691                 }
6692                 result = winreg_set_printer_dataex(tmp_ctx, b,
6693                                           printer->sharename,
6694                                           SPOOL_DSSPOOLER_KEY,
6695                                           SPOOL_REG_PRINTSEPARATORFILE,
6696                                           REG_SZ,
6697                                           buffer.data,
6698                                           buffer.length);
6699                 if (!W_ERROR_IS_OK(result)) {
6700                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6701                         goto done;
6702                 }
6703
6704                 if (!force_update) {
6705                         notify_printer_sepfile(server_event_context(),
6706                                                msg_ctx, snum,
6707                                                printer->sepfile ?
6708                                                printer->sepfile : "");
6709                 }
6710         }
6711
6712         if (printer->starttime != 0 &&
6713             (force_update ||
6714              printer->starttime != old_printer->starttime)) {
6715                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6716                 SIVAL(buffer.data, 0, printer->starttime);
6717                 result = winreg_set_printer_dataex(tmp_ctx, b,
6718                                           printer->sharename,
6719                                           SPOOL_DSSPOOLER_KEY,
6720                                           SPOOL_REG_PRINTSTARTTIME,
6721                                           REG_DWORD,
6722                                           buffer.data,
6723                                           buffer.length);
6724                 if (!W_ERROR_IS_OK(result)) {
6725                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6726                         goto done;
6727                 }
6728         }
6729
6730         if (printer->untiltime != 0 &&
6731             (force_update ||
6732              printer->untiltime != old_printer->untiltime)) {
6733                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6734                 SIVAL(buffer.data, 0, printer->untiltime);
6735                 result = winreg_set_printer_dataex(tmp_ctx, b,
6736                                           printer->sharename,
6737                                           SPOOL_DSSPOOLER_KEY,
6738                                           SPOOL_REG_PRINTENDTIME,
6739                                           REG_DWORD,
6740                                           buffer.data,
6741                                           buffer.length);
6742                 if (!W_ERROR_IS_OK(result)) {
6743                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6744                         goto done;
6745                 }
6746         }
6747
6748         if (force_update || printer->priority != old_printer->priority) {
6749                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6750                 SIVAL(buffer.data, 0, printer->priority);
6751                 result = winreg_set_printer_dataex(tmp_ctx, b,
6752                                           printer->sharename,
6753                                           SPOOL_DSSPOOLER_KEY,
6754                                           SPOOL_REG_PRIORITY,
6755                                           REG_DWORD,
6756                                           buffer.data,
6757                                           buffer.length);
6758                 if (!W_ERROR_IS_OK(result)) {
6759                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6760                         goto done;
6761                 }
6762         }
6763
6764         if (force_update || printer->attributes != old_printer->attributes) {
6765                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6766                 SIVAL(buffer.data, 0, (printer->attributes &
6767                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6768                 result = winreg_set_printer_dataex(tmp_ctx, b,
6769                                           printer->sharename,
6770                                           SPOOL_DSSPOOLER_KEY,
6771                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6772                                           REG_DWORD,
6773                                           buffer.data,
6774                                           buffer.length);
6775                 if (!W_ERROR_IS_OK(result)) {
6776                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6777                         goto done;
6778                 }
6779
6780                 switch (printer->attributes & 0x3) {
6781                         case 0:
6782                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6783                                 break;
6784                         case 1:
6785                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6786                                 break;
6787                         case 2:
6788                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6789                                 break;
6790                         default:
6791                                 spooling = "unknown";
6792                 }
6793                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6794                 if (!ok) {
6795                         DEBUG(0, ("printSpooling data corrupted\n"));
6796                         result = WERR_INVALID_DATA;
6797                         goto done;
6798                 }
6799                 winreg_set_printer_dataex(tmp_ctx, b,
6800                                           printer->sharename,
6801                                           SPOOL_DSSPOOLER_KEY,
6802                                           SPOOL_REG_PRINTSPOOLING,
6803                                           REG_SZ,
6804                                           buffer.data,
6805                                           buffer.length);
6806         }
6807
6808         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6809         if (!ok) {
6810                 DEBUG(0, ("shortServerName data corrupted\n"));
6811                 result = WERR_INVALID_DATA;
6812                 goto done;
6813         }
6814         result = winreg_set_printer_dataex(tmp_ctx, b,
6815                                   printer->sharename,
6816                                   SPOOL_DSSPOOLER_KEY,
6817                                   SPOOL_REG_SHORTSERVERNAME,
6818                                   REG_SZ,
6819                                   buffer.data,
6820                                   buffer.length);
6821         if (!W_ERROR_IS_OK(result)) {
6822                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6823                 goto done;
6824         }
6825
6826         dnsdomname = get_mydnsfullname();
6827         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6828                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6829         } else {
6830                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6831         }
6832         if (longname == NULL) {
6833                 result = WERR_NOT_ENOUGH_MEMORY;
6834                 goto done;
6835         }
6836
6837         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6838         if (!ok) {
6839                 DEBUG(0, ("longname data corrupted\n"));
6840                 result = WERR_INVALID_DATA;
6841                 goto done;
6842         }
6843         result = winreg_set_printer_dataex(tmp_ctx, b,
6844                                            printer->sharename,
6845                                            SPOOL_DSSPOOLER_KEY,
6846                                            SPOOL_REG_SERVERNAME,
6847                                            REG_SZ,
6848                                            buffer.data,
6849                                            buffer.length);
6850         if (!W_ERROR_IS_OK(result)) {
6851                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6852                 goto done;
6853         }
6854
6855         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6856                                   lp_netbios_name(), printer->sharename);
6857         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6858         if (!ok) {
6859                 DEBUG(0, ("uncName data corrupted\n"));
6860                 result = WERR_INVALID_DATA;
6861                 goto done;
6862         }
6863         result = winreg_set_printer_dataex(tmp_ctx, b,
6864                                   printer->sharename,
6865                                   SPOOL_DSSPOOLER_KEY,
6866                                   SPOOL_REG_UNCNAME,
6867                                   REG_SZ,
6868                                   buffer.data,
6869                                   buffer.length);
6870         if (!W_ERROR_IS_OK(result)) {
6871                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6872                 goto done;
6873         }
6874
6875 done:
6876         talloc_free(tmp_ctx);
6877         return result;
6878 }
6879
6880 /********************************************************************
6881  * Called by spoolss_api_setprinter
6882  * when updating a printer description.
6883  ********************************************************************/
6884
6885 static WERROR update_printer(struct pipes_struct *p,
6886                              struct policy_handle *handle,
6887                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6888                              struct spoolss_DeviceMode *devmode)
6889 {
6890         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6891         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6892         struct spoolss_PrinterInfo2 *old_printer;
6893         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6894         int snum;
6895         WERROR result = WERR_OK;
6896         TALLOC_CTX *tmp_ctx;
6897         struct dcerpc_binding_handle *b;
6898
6899         DEBUG(8,("update_printer\n"));
6900
6901         tmp_ctx = talloc_new(p->mem_ctx);
6902         if (tmp_ctx == NULL) {
6903                 return WERR_NOT_ENOUGH_MEMORY;
6904         }
6905
6906         if (!Printer) {
6907                 result = WERR_INVALID_HANDLE;
6908                 goto done;
6909         }
6910
6911         if (!get_printer_snum(p, handle, &snum, NULL)) {
6912                 result = WERR_INVALID_HANDLE;
6913                 goto done;
6914         }
6915
6916         result = winreg_printer_binding_handle(tmp_ctx,
6917                                                get_session_info_system(),
6918                                                p->msg_ctx,
6919                                                &b);
6920         if (!W_ERROR_IS_OK(result)) {
6921                 goto done;
6922         }
6923
6924         result = winreg_get_printer(tmp_ctx, b,
6925                                     lp_const_servicename(snum),
6926                                     &old_printer);
6927         if (!W_ERROR_IS_OK(result)) {
6928                 result = WERR_INVALID_HANDLE;
6929                 goto done;
6930         }
6931
6932         /* Do sanity check on the requested changes for Samba */
6933         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6934                 result = WERR_INVALID_PARAMETER;
6935                 goto done;
6936         }
6937
6938         /* FIXME!!! If the driver has changed we really should verify that
6939            it is installed before doing much else   --jerry */
6940
6941         /* Check calling user has permission to update printer description */
6942         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6943                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6944                 result = WERR_ACCESS_DENIED;
6945                 goto done;
6946         }
6947
6948         /* Call addprinter hook */
6949         /* Check changes to see if this is really needed */
6950
6951         if (*lp_addprinter_command(talloc_tos()) &&
6952                         (!strequal(printer->drivername, old_printer->drivername) ||
6953                          !strequal(printer->comment, old_printer->comment) ||
6954                          !strequal(printer->portname, old_printer->portname) ||
6955                          !strequal(printer->location, old_printer->location)) )
6956         {
6957                 char *raddr;
6958
6959                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6960                                                          p->mem_ctx);
6961                 if (raddr == NULL) {
6962                         return WERR_NOT_ENOUGH_MEMORY;
6963                 }
6964
6965                 /* add_printer_hook() will call reload_services() */
6966                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6967                                       printer, raddr,
6968                                       p->msg_ctx)) {
6969                         result = WERR_ACCESS_DENIED;
6970                         goto done;
6971                 }
6972         }
6973
6974         result = update_dsspooler(tmp_ctx,
6975                                   get_session_info_system(),
6976                                   p->msg_ctx,
6977                                   snum,
6978                                   printer,
6979                                   old_printer);
6980         if (!W_ERROR_IS_OK(result)) {
6981                 goto done;
6982         }
6983
6984         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6985
6986         if (devmode == NULL) {
6987                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6988         }
6989         result = winreg_update_printer(tmp_ctx, b,
6990                                        printer->sharename,
6991                                        printer_mask,
6992                                        printer,
6993                                        devmode,
6994                                        NULL);
6995
6996 done:
6997         talloc_free(tmp_ctx);
6998
6999         return result;
7000 }
7001
7002 /****************************************************************************
7003 ****************************************************************************/
7004 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
7005                                            struct policy_handle *handle,
7006                                            struct spoolss_SetPrinterInfo7 *info7)
7007 {
7008 #ifdef HAVE_ADS
7009         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7010         WERROR result;
7011         int snum;
7012         struct printer_handle *Printer;
7013
7014         if ( lp_security() != SEC_ADS ) {
7015                 return WERR_INVALID_LEVEL;
7016         }
7017
7018         Printer = find_printer_index_by_hnd(p, handle);
7019
7020         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
7021
7022         if (!Printer)
7023                 return WERR_INVALID_HANDLE;
7024
7025         if (!get_printer_snum(p, handle, &snum, NULL))
7026                 return WERR_INVALID_HANDLE;
7027
7028         result = winreg_get_printer_internal(p->mem_ctx,
7029                                     get_session_info_system(),
7030                                     p->msg_ctx,
7031                                     lp_servicename(talloc_tos(), snum),
7032                                     &pinfo2);
7033         if (!W_ERROR_IS_OK(result)) {
7034                 return WERR_INVALID_HANDLE;
7035         }
7036
7037         nt_printer_publish(pinfo2,
7038                            get_session_info_system(),
7039                            p->msg_ctx,
7040                            pinfo2,
7041                            info7->action);
7042
7043         TALLOC_FREE(pinfo2);
7044         return WERR_OK;
7045 #else
7046         return WERR_INVALID_LEVEL;
7047 #endif
7048 }
7049
7050 /********************************************************************
7051  ********************************************************************/
7052
7053 static WERROR update_printer_devmode(struct pipes_struct *p,
7054                                      struct policy_handle *handle,
7055                                      struct spoolss_DeviceMode *devmode)
7056 {
7057         int snum;
7058         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7059         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
7060
7061         DEBUG(8,("update_printer_devmode\n"));
7062
7063         if (!Printer) {
7064                 return WERR_INVALID_HANDLE;
7065         }
7066
7067         if (!get_printer_snum(p, handle, &snum, NULL)) {
7068                 return WERR_INVALID_HANDLE;
7069         }
7070
7071         /* Check calling user has permission to update printer description */
7072         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7073                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7074                 return WERR_ACCESS_DENIED;
7075         }
7076
7077         return winreg_update_printer_internal(p->mem_ctx,
7078                                      get_session_info_system(),
7079                                      p->msg_ctx,
7080                                      lp_const_servicename(snum),
7081                                      info2_mask,
7082                                      NULL,
7083                                      devmode,
7084                                      NULL);
7085 }
7086
7087
7088 /****************************************************************
7089  _spoolss_SetPrinter
7090 ****************************************************************/
7091
7092 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
7093                            struct spoolss_SetPrinter *r)
7094 {
7095         WERROR result;
7096
7097         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7098
7099         if (!Printer) {
7100                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
7101                         OUR_HANDLE(r->in.handle)));
7102                 return WERR_INVALID_HANDLE;
7103         }
7104
7105         /* check the level */
7106         switch (r->in.info_ctr->level) {
7107                 case 0:
7108                         return control_printer(r->in.handle, r->in.command, p);
7109                 case 2:
7110                         result = update_printer(p, r->in.handle,
7111                                                 r->in.info_ctr,
7112                                                 r->in.devmode_ctr->devmode);
7113                         if (!W_ERROR_IS_OK(result))
7114                                 return result;
7115                         if (r->in.secdesc_ctr->sd)
7116                                 result = update_printer_sec(r->in.handle, p,
7117                                                             r->in.secdesc_ctr);
7118                         return result;
7119                 case 3:
7120                         return update_printer_sec(r->in.handle, p,
7121                                                   r->in.secdesc_ctr);
7122                 case 4: {
7123                         struct spoolss_PrinterInfo2 *old_printer;
7124                         struct spoolss_SetPrinterInfo2 *set_old_printer;
7125                         struct spoolss_SetPrinterInfoCtr *info_ctr;
7126                         struct dcerpc_binding_handle *b;
7127                         int snum;
7128                         TALLOC_CTX *tmp_ctx;
7129
7130                         tmp_ctx = talloc_new(p->mem_ctx);
7131                         if (tmp_ctx == NULL) {
7132                                 return WERR_NOT_ENOUGH_MEMORY;
7133                         }
7134
7135                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7136                                 TALLOC_FREE(tmp_ctx);
7137                                 return WERR_INVALID_HANDLE;
7138                         }
7139
7140                         result = winreg_printer_binding_handle(tmp_ctx,
7141                                                                get_session_info_system(),
7142                                                                p->msg_ctx,
7143                                                                &b);
7144                         if (!W_ERROR_IS_OK(result)) {
7145                                 TALLOC_FREE(tmp_ctx);
7146                                 return result;
7147                         }
7148
7149                         result = winreg_get_printer(tmp_ctx, b,
7150                                                     lp_const_servicename(snum),
7151                                                     &old_printer);
7152                         if (!W_ERROR_IS_OK(result)) {
7153                                 TALLOC_FREE(tmp_ctx);
7154                                 return WERR_INVALID_HANDLE;
7155                         }
7156
7157                         old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
7158                         if (old_printer->servername == NULL) {
7159                                 TALLOC_FREE(tmp_ctx);
7160                                 return WERR_NOT_ENOUGH_MEMORY;
7161                         }
7162
7163                         old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
7164                         if (old_printer->printername == NULL) {
7165                                 TALLOC_FREE(tmp_ctx);
7166                                 return WERR_NOT_ENOUGH_MEMORY;
7167                         }
7168
7169                         old_printer->attributes = r->in.info_ctr->info.info4->attributes;
7170
7171                         set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
7172                         if (set_old_printer == NULL) {
7173                                 TALLOC_FREE(tmp_ctx);
7174                                 return WERR_NOT_ENOUGH_MEMORY;
7175                         }
7176
7177                         spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
7178
7179                         info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
7180                         if (info_ctr == NULL) {
7181                                 TALLOC_FREE(tmp_ctx);
7182                                 return WERR_NOT_ENOUGH_MEMORY;
7183                         }
7184
7185                         info_ctr->level = 2;
7186                         info_ctr->info.info2 = set_old_printer;
7187
7188                         result = update_printer(p, r->in.handle,
7189                                                 info_ctr,
7190                                                 r->in.devmode_ctr->devmode);
7191
7192                         if (!W_ERROR_IS_OK(result)) {
7193                                 TALLOC_FREE(tmp_ctx);
7194                                 return result;
7195                         }
7196
7197                         if (r->in.secdesc_ctr->sd) {
7198                                 result = update_printer_sec(r->in.handle, p,
7199                                                             r->in.secdesc_ctr);
7200                         }
7201
7202                         TALLOC_FREE(tmp_ctx);
7203                         return result;
7204                 }
7205                 case 7:
7206                         return publish_or_unpublish_printer(p, r->in.handle,
7207                                                             r->in.info_ctr->info.info7);
7208                 case 8:
7209                         return update_printer_devmode(p, r->in.handle,
7210                                                       r->in.devmode_ctr->devmode);
7211                 default:
7212                         return WERR_INVALID_LEVEL;
7213         }
7214 }
7215
7216 /****************************************************************
7217  _spoolss_FindClosePrinterNotify
7218 ****************************************************************/
7219
7220 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7221                                        struct spoolss_FindClosePrinterNotify *r)
7222 {
7223         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7224
7225         if (!Printer) {
7226                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7227                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7228                 return WERR_INVALID_HANDLE;
7229         }
7230
7231         if (Printer->notify.cli_chan != NULL &&
7232             Printer->notify.cli_chan->active_connections > 0) {
7233                 int snum = -1;
7234
7235                 if (Printer->printer_type == SPLHND_PRINTER) {
7236                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7237                                 return WERR_INVALID_HANDLE;
7238                         }
7239                 }
7240
7241                 srv_spoolss_replycloseprinter(snum, Printer);
7242         }
7243
7244         Printer->notify.flags=0;
7245         Printer->notify.options=0;
7246         Printer->notify.localmachine[0]='\0';
7247         Printer->notify.printerlocal=0;
7248         TALLOC_FREE(Printer->notify.option);
7249
7250         return WERR_OK;
7251 }
7252
7253 /****************************************************************
7254  _spoolss_AddJob
7255 ****************************************************************/
7256
7257 WERROR _spoolss_AddJob(struct pipes_struct *p,
7258                        struct spoolss_AddJob *r)
7259 {
7260         if (!r->in.buffer && (r->in.offered != 0)) {
7261                 return WERR_INVALID_PARAMETER;
7262         }
7263
7264         /* this is what a NT server returns for AddJob. AddJob must fail on
7265          * non-local printers */
7266
7267         if (r->in.level != 1) {
7268                 return WERR_INVALID_LEVEL;
7269         }
7270
7271         return WERR_INVALID_PARAMETER;
7272 }
7273
7274 /****************************************************************************
7275 fill_job_info1
7276 ****************************************************************************/
7277
7278 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7279                              struct spoolss_JobInfo1 *r,
7280                              const print_queue_struct *queue,
7281                              uint32_t jobid,
7282                              int position, int snum,
7283                              struct spoolss_PrinterInfo2 *pinfo2)
7284 {
7285         struct tm *t;
7286
7287         t = gmtime(&queue->time);
7288
7289         r->job_id               = jobid;
7290
7291         r->printer_name         = lp_servicename(mem_ctx, snum);
7292         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7293         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7294         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7295         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7296         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7297         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7298         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7299         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7300         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7301         r->text_status          = talloc_strdup(mem_ctx, "");
7302         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7303
7304         r->status               = nt_printj_status(queue->status);
7305         r->priority             = queue->priority;
7306         r->position             = position;
7307         r->total_pages          = queue->page_count;
7308         r->pages_printed        = 0; /* ??? */
7309
7310         init_systemtime(&r->submitted, t);
7311
7312         return WERR_OK;
7313 }
7314
7315 /****************************************************************************
7316 fill_job_info2
7317 ****************************************************************************/
7318
7319 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7320                              struct spoolss_JobInfo2 *r,
7321                              const print_queue_struct *queue,
7322                              uint32_t jobid,
7323                              int position, int snum,
7324                              struct spoolss_PrinterInfo2 *pinfo2,
7325                              struct spoolss_DeviceMode *devmode)
7326 {
7327         struct tm *t;
7328
7329         t = gmtime(&queue->time);
7330
7331         r->job_id               = jobid;
7332
7333         r->printer_name         = lp_servicename(mem_ctx, snum);
7334         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7335         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7336         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7337         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7338         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7339         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7340         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7341         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7342         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7343         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7344         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7345         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7346         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7347         r->parameters           = talloc_strdup(mem_ctx, "");
7348         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7349         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7350         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7351
7352         r->devmode              = devmode;
7353
7354         r->text_status          = talloc_strdup(mem_ctx, "");
7355         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7356
7357         r->secdesc              = NULL;
7358
7359         r->status               = nt_printj_status(queue->status);
7360         r->priority             = queue->priority;
7361         r->position             = position;
7362         r->start_time           = 0;
7363         r->until_time           = 0;
7364         r->total_pages          = queue->page_count;
7365         r->size                 = queue->size;
7366         init_systemtime(&r->submitted, t);
7367         r->time                 = 0;
7368         r->pages_printed        = 0; /* ??? */
7369
7370         return WERR_OK;
7371 }
7372
7373 /****************************************************************************
7374  Enumjobs at level 1.
7375 ****************************************************************************/
7376
7377 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7378                               const print_queue_struct *queue,
7379                               uint32_t num_queues, int snum,
7380                               struct spoolss_PrinterInfo2 *pinfo2,
7381                               union spoolss_JobInfo **info_p,
7382                               uint32_t *count)
7383 {
7384         union spoolss_JobInfo *info;
7385         int i;
7386         WERROR result = WERR_OK;
7387         uint32_t num_filled;
7388         struct tdb_print_db *pdb;
7389
7390         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7391         if (info == NULL) {
7392                 result = WERR_NOT_ENOUGH_MEMORY;
7393                 goto err_out;
7394         }
7395
7396         pdb = get_print_db_byname(pinfo2->sharename);
7397         if (pdb == NULL) {
7398                 result = WERR_INVALID_PARAMETER;
7399                 goto err_info_free;
7400         }
7401
7402         num_filled = 0;
7403         for (i = 0; i < num_queues; i++) {
7404                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7405                 if (jobid == (uint32_t)-1) {
7406                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7407                         continue;
7408                 }
7409
7410                 result = fill_job_info1(info,
7411                                         &info[num_filled].info1,
7412                                         &queue[i],
7413                                         jobid,
7414                                         i,
7415                                         snum,
7416                                         pinfo2);
7417                 if (!W_ERROR_IS_OK(result)) {
7418                         goto err_pdb_drop;
7419                 }
7420
7421                 num_filled++;
7422         }
7423
7424         release_print_db(pdb);
7425         *info_p = info;
7426         *count = num_filled;
7427
7428         return WERR_OK;
7429
7430 err_pdb_drop:
7431         release_print_db(pdb);
7432 err_info_free:
7433         TALLOC_FREE(info);
7434 err_out:
7435         *count = 0;
7436         return result;
7437 }
7438
7439 /****************************************************************************
7440  Enumjobs at level 2.
7441 ****************************************************************************/
7442
7443 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7444                               const print_queue_struct *queue,
7445                               uint32_t num_queues, int snum,
7446                               struct spoolss_PrinterInfo2 *pinfo2,
7447                               union spoolss_JobInfo **info_p,
7448                               uint32_t *count)
7449 {
7450         union spoolss_JobInfo *info;
7451         int i;
7452         WERROR result = WERR_OK;
7453         uint32_t num_filled;
7454         struct tdb_print_db *pdb;
7455
7456         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7457         if (info == NULL) {
7458                 result = WERR_NOT_ENOUGH_MEMORY;
7459                 goto err_out;
7460         }
7461
7462         pdb = get_print_db_byname(pinfo2->sharename);
7463         if (pdb == NULL) {
7464                 result = WERR_INVALID_PARAMETER;
7465                 goto err_info_free;
7466         }
7467
7468         num_filled = 0;
7469         for (i = 0; i< num_queues; i++) {
7470                 struct spoolss_DeviceMode *devmode;
7471                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7472                 if (jobid == (uint32_t)-1) {
7473                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7474                         continue;
7475                 }
7476
7477                 result = spoolss_create_default_devmode(info,
7478                                                         pinfo2->printername,
7479                                                         &devmode);
7480                 if (!W_ERROR_IS_OK(result)) {
7481                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7482                         goto err_pdb_drop;
7483                 }
7484
7485                 result = fill_job_info2(info,
7486                                         &info[num_filled].info2,
7487                                         &queue[i],
7488                                         jobid,
7489                                         i,
7490                                         snum,
7491                                         pinfo2,
7492                                         devmode);
7493                 if (!W_ERROR_IS_OK(result)) {
7494                         goto err_pdb_drop;
7495                 }
7496                 num_filled++;
7497         }
7498
7499         release_print_db(pdb);
7500         *info_p = info;
7501         *count = num_filled;
7502
7503         return WERR_OK;
7504
7505 err_pdb_drop:
7506         release_print_db(pdb);
7507 err_info_free:
7508         TALLOC_FREE(info);
7509 err_out:
7510         *count = 0;
7511         return result;
7512 }
7513
7514 /****************************************************************************
7515  Enumjobs at level 3.
7516 ****************************************************************************/
7517
7518 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7519                               const print_queue_struct *queue,
7520                               uint32_t num_queues, int snum,
7521                               struct spoolss_PrinterInfo2 *pinfo2,
7522                               union spoolss_JobInfo **info_p,
7523                               uint32_t *count)
7524 {
7525         union spoolss_JobInfo *info;
7526         int i;
7527         WERROR result = WERR_OK;
7528         uint32_t num_filled;
7529         struct tdb_print_db *pdb;
7530
7531         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7532         if (info == NULL) {
7533                 result = WERR_NOT_ENOUGH_MEMORY;
7534                 goto err_out;
7535         }
7536
7537         pdb = get_print_db_byname(pinfo2->sharename);
7538         if (pdb == NULL) {
7539                 result = WERR_INVALID_PARAMETER;
7540                 goto err_info_free;
7541         }
7542
7543         num_filled = 0;
7544         for (i = 0; i < num_queues; i++) {
7545                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7546                 if (jobid == (uint32_t)-1) {
7547                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7548                         continue;
7549                 }
7550
7551                 info[num_filled].info3.job_id = jobid;
7552                 /* next_job_id is overwritten on next iteration */
7553                 info[num_filled].info3.next_job_id = 0;
7554                 info[num_filled].info3.reserved = 0;
7555
7556                 if (num_filled > 0) {
7557                         info[num_filled - 1].info3.next_job_id = jobid;
7558                 }
7559                 num_filled++;
7560         }
7561
7562         release_print_db(pdb);
7563         *info_p = info;
7564         *count = num_filled;
7565
7566         return WERR_OK;
7567
7568 err_info_free:
7569         TALLOC_FREE(info);
7570 err_out:
7571         *count = 0;
7572         return result;
7573 }
7574
7575 /****************************************************************
7576  _spoolss_EnumJobs
7577 ****************************************************************/
7578
7579 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7580                          struct spoolss_EnumJobs *r)
7581 {
7582         WERROR result;
7583         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7584         int snum;
7585         print_status_struct prt_status;
7586         print_queue_struct *queue = NULL;
7587         uint32_t count;
7588
7589         /* that's an [in out] buffer */
7590
7591         if (!r->in.buffer && (r->in.offered != 0)) {
7592                 return WERR_INVALID_PARAMETER;
7593         }
7594
7595         if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7596                 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7597                 return WERR_INVALID_LEVEL;
7598         }
7599
7600         DEBUG(4,("_spoolss_EnumJobs\n"));
7601
7602         *r->out.needed = 0;
7603         *r->out.count = 0;
7604         *r->out.info = NULL;
7605
7606         /* lookup the printer snum and tdb entry */
7607
7608         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7609                 return WERR_INVALID_HANDLE;
7610         }
7611
7612         result = winreg_get_printer_internal(p->mem_ctx,
7613                                     get_session_info_system(),
7614                                     p->msg_ctx,
7615                                     lp_const_servicename(snum),
7616                                     &pinfo2);
7617         if (!W_ERROR_IS_OK(result)) {
7618                 return result;
7619         }
7620
7621         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7622         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7623                 count, prt_status.status, prt_status.message));
7624
7625         if (count == 0) {
7626                 SAFE_FREE(queue);
7627                 TALLOC_FREE(pinfo2);
7628                 return WERR_OK;
7629         }
7630
7631         switch (r->in.level) {
7632         case 1:
7633                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7634                                          pinfo2, r->out.info, r->out.count);
7635                 break;
7636         case 2:
7637                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7638                                          pinfo2, r->out.info, r->out.count);
7639                 break;
7640         case 3:
7641                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7642                                          pinfo2, r->out.info, r->out.count);
7643                 break;
7644         default:
7645                 SMB_ASSERT(false);      /* level checked on entry */
7646                 break;
7647         }
7648
7649         SAFE_FREE(queue);
7650         TALLOC_FREE(pinfo2);
7651
7652         if (!W_ERROR_IS_OK(result)) {
7653                 return result;
7654         }
7655
7656         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7657                                                      spoolss_EnumJobs,
7658                                                      *r->out.info, r->in.level,
7659                                                      *r->out.count);
7660         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7661         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7662
7663         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7664 }
7665
7666 /****************************************************************
7667  _spoolss_ScheduleJob
7668 ****************************************************************/
7669
7670 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7671                             struct spoolss_ScheduleJob *r)
7672 {
7673         return WERR_OK;
7674 }
7675
7676 /****************************************************************
7677 ****************************************************************/
7678
7679 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7680                                struct messaging_context *msg_ctx,
7681                                const char *printer_name,
7682                                uint32_t job_id,
7683                                struct spoolss_SetJobInfo1 *r)
7684 {
7685         char *old_doc_name;
7686
7687         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7688                 return WERR_INVALID_HANDLE;
7689         }
7690
7691         if (strequal(old_doc_name, r->document_name)) {
7692                 return WERR_OK;
7693         }
7694
7695         if (!print_job_set_name(server_event_context(), msg_ctx,
7696                                 printer_name, job_id, r->document_name)) {
7697                 return WERR_INVALID_HANDLE;
7698         }
7699
7700         return WERR_OK;
7701 }
7702
7703 /****************************************************************
7704  _spoolss_SetJob
7705 ****************************************************************/
7706
7707 WERROR _spoolss_SetJob(struct pipes_struct *p,
7708                        struct spoolss_SetJob *r)
7709 {
7710         const struct auth_session_info *session_info = p->session_info;
7711         int snum;
7712         WERROR errcode = WERR_INVALID_FUNCTION;
7713
7714         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7715                 return WERR_INVALID_HANDLE;
7716         }
7717
7718         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7719                 return WERR_INVALID_PRINTER_NAME;
7720         }
7721
7722         switch (r->in.command) {
7723         case SPOOLSS_JOB_CONTROL_CANCEL:
7724         case SPOOLSS_JOB_CONTROL_DELETE:
7725                 errcode = print_job_delete(session_info, p->msg_ctx,
7726                                            snum, r->in.job_id);
7727                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7728                         errcode = WERR_OK;
7729                 }
7730                 break;
7731         case SPOOLSS_JOB_CONTROL_PAUSE:
7732                 errcode = print_job_pause(session_info, p->msg_ctx,
7733                                           snum, r->in.job_id);
7734                 break;
7735         case SPOOLSS_JOB_CONTROL_RESTART:
7736         case SPOOLSS_JOB_CONTROL_RESUME:
7737                 errcode = print_job_resume(session_info, p->msg_ctx,
7738                                            snum, r->in.job_id);
7739                 break;
7740         case SPOOLSS_JOB_CONTROL_NOOP:
7741                 errcode = WERR_OK;
7742                 break;
7743         default:
7744                 return WERR_INVALID_LEVEL;
7745         }
7746
7747         if (!W_ERROR_IS_OK(errcode)) {
7748                 return errcode;
7749         }
7750
7751         if (r->in.ctr == NULL) {
7752                 return errcode;
7753         }
7754
7755         switch (r->in.ctr->level) {
7756         case 1:
7757                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7758                                            lp_const_servicename(snum),
7759                                            r->in.job_id,
7760                                            r->in.ctr->info.info1);
7761                 break;
7762         case 2:
7763         case 3:
7764         case 4:
7765         default:
7766                 return WERR_INVALID_LEVEL;
7767         }
7768
7769         return errcode;
7770 }
7771
7772 /****************************************************************************
7773  Enumerates all printer drivers by level and architecture.
7774 ****************************************************************************/
7775
7776 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7777                                                        const struct auth_session_info *session_info,
7778                                                        struct messaging_context *msg_ctx,
7779                                                        const char *servername,
7780                                                        const char *architecture,
7781                                                        uint32_t level,
7782                                                        union spoolss_DriverInfo **info_p,
7783                                                        uint32_t *count_p)
7784 {
7785         int i;
7786         uint32_t version;
7787         struct spoolss_DriverInfo8 *driver;
7788         union spoolss_DriverInfo *info = NULL;
7789         uint32_t count = 0;
7790         WERROR result = WERR_OK;
7791         uint32_t num_drivers;
7792         const char **drivers;
7793         struct dcerpc_binding_handle *b;
7794         TALLOC_CTX *tmp_ctx = NULL;
7795
7796         *count_p = 0;
7797         *info_p = NULL;
7798
7799         tmp_ctx = talloc_new(mem_ctx);
7800         if (!tmp_ctx) {
7801                 return WERR_NOT_ENOUGH_MEMORY;
7802         }
7803
7804         result = winreg_printer_binding_handle(tmp_ctx,
7805                                                session_info,
7806                                                msg_ctx,
7807                                                &b);
7808         if (!W_ERROR_IS_OK(result)) {
7809                 goto out;
7810         }
7811
7812         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7813                 result = winreg_get_driver_list(tmp_ctx, b,
7814                                                 architecture, version,
7815                                                 &num_drivers, &drivers);
7816                 if (!W_ERROR_IS_OK(result)) {
7817                         goto out;
7818                 }
7819                 DEBUG(4, ("we have:[%d] drivers in environment"
7820                           " [%s] and version [%d]\n",
7821                           num_drivers, architecture, version));
7822
7823                 if (num_drivers != 0) {
7824                         info = talloc_realloc(tmp_ctx, info,
7825                                                     union spoolss_DriverInfo,
7826                                                     count + num_drivers);
7827                         if (!info) {
7828                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7829                                         "failed to enlarge driver info buffer!\n"));
7830                                 result = WERR_NOT_ENOUGH_MEMORY;
7831                                 goto out;
7832                         }
7833                 }
7834
7835                 for (i = 0; i < num_drivers; i++) {
7836                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7837
7838                         result = winreg_get_driver(tmp_ctx, b,
7839                                                    architecture, drivers[i],
7840                                                    version, &driver);
7841                         if (!W_ERROR_IS_OK(result)) {
7842                                 goto out;
7843                         }
7844
7845                         switch (level) {
7846                         case 1:
7847                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7848                                                                    driver, servername);
7849                                 break;
7850                         case 2:
7851                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7852                                                                    driver, servername);
7853                                 break;
7854                         case 3:
7855                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7856                                                                    driver, servername);
7857                                 break;
7858                         case 4:
7859                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7860                                                                    driver, servername);
7861                                 break;
7862                         case 5:
7863                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7864                                                                    driver, servername);
7865                                 break;
7866                         case 6:
7867                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7868                                                                    driver, servername);
7869                                 break;
7870                         case 8:
7871                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7872                                                                    driver, servername);
7873                                 break;
7874                         default:
7875                                 result = WERR_INVALID_LEVEL;
7876                                 break;
7877                         }
7878
7879                         TALLOC_FREE(driver);
7880
7881                         if (!W_ERROR_IS_OK(result)) {
7882                                 goto out;
7883                         }
7884                 }
7885
7886                 count += num_drivers;
7887                 TALLOC_FREE(drivers);
7888         }
7889
7890 out:
7891         if (W_ERROR_IS_OK(result)) {
7892                 *info_p = talloc_move(mem_ctx, &info);
7893                 *count_p = count;
7894         }
7895
7896         talloc_free(tmp_ctx);
7897         return result;
7898 }
7899
7900 /****************************************************************************
7901  Enumerates all printer drivers by level.
7902 ****************************************************************************/
7903
7904 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7905                                        const struct auth_session_info *session_info,
7906                                        struct messaging_context *msg_ctx,
7907                                        const char *servername,
7908                                        const char *architecture,
7909                                        uint32_t level,
7910                                        union spoolss_DriverInfo **info_p,
7911                                        uint32_t *count_p)
7912 {
7913         uint32_t a,i;
7914         WERROR result = WERR_OK;
7915
7916         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7917
7918                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7919
7920                         union spoolss_DriverInfo *info = NULL;
7921                         uint32_t count = 0;
7922
7923                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7924                                                                           session_info,
7925                                                                           msg_ctx,
7926                                                                           servername,
7927                                                                           archi_table[a].long_archi,
7928                                                                           level,
7929                                                                           &info,
7930                                                                           &count);
7931                         if (!W_ERROR_IS_OK(result)) {
7932                                 continue;
7933                         }
7934
7935                         for (i=0; i < count; i++) {
7936                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7937                                              info[i], info_p, count_p);
7938                         }
7939                 }
7940
7941                 return result;
7942         }
7943
7944         return enumprinterdrivers_level_by_architecture(mem_ctx,
7945                                                         session_info,
7946                                                         msg_ctx,
7947                                                         servername,
7948                                                         architecture,
7949                                                         level,
7950                                                         info_p,
7951                                                         count_p);
7952 }
7953
7954 /****************************************************************
7955  _spoolss_EnumPrinterDrivers
7956 ****************************************************************/
7957
7958 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7959                                    struct spoolss_EnumPrinterDrivers *r)
7960 {
7961         const char *cservername;
7962         WERROR result;
7963
7964         /* that's an [in out] buffer */
7965
7966         if (!r->in.buffer && (r->in.offered != 0)) {
7967                 return WERR_INVALID_PARAMETER;
7968         }
7969
7970         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7971
7972         *r->out.needed = 0;
7973         *r->out.count = 0;
7974         *r->out.info = NULL;
7975
7976         cservername = canon_servername(r->in.server);
7977
7978         if (!is_myname_or_ipaddr(cservername)) {
7979                 return WERR_UNKNOWN_PRINTER_DRIVER;
7980         }
7981
7982         result = enumprinterdrivers_level(p->mem_ctx,
7983                                           get_session_info_system(),
7984                                           p->msg_ctx,
7985                                           cservername,
7986                                           r->in.environment,
7987                                           r->in.level,
7988                                           r->out.info,
7989                                           r->out.count);
7990         if (!W_ERROR_IS_OK(result)) {
7991                 return result;
7992         }
7993
7994         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7995                                                      spoolss_EnumPrinterDrivers,
7996                                                      *r->out.info, r->in.level,
7997                                                      *r->out.count);
7998         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7999         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8000
8001         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8002 }
8003
8004 /****************************************************************
8005  _spoolss_EnumForms
8006 ****************************************************************/
8007
8008 WERROR _spoolss_EnumForms(struct pipes_struct *p,
8009                           struct spoolss_EnumForms *r)
8010 {
8011         WERROR result;
8012
8013         *r->out.count = 0;
8014         *r->out.needed = 0;
8015         *r->out.info = NULL;
8016
8017         /* that's an [in out] buffer */
8018
8019         if (!r->in.buffer && (r->in.offered != 0) ) {
8020                 return WERR_INVALID_PARAMETER;
8021         }
8022
8023         DEBUG(4,("_spoolss_EnumForms\n"));
8024         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8025         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
8026
8027         switch (r->in.level) {
8028         case 1:
8029                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
8030                                                    get_session_info_system(),
8031                                                    p->msg_ctx,
8032                                                    r->out.count,
8033                                                    r->out.info);
8034                 break;
8035         default:
8036                 result = WERR_INVALID_LEVEL;
8037                 break;
8038         }
8039
8040         if (!W_ERROR_IS_OK(result)) {
8041                 return result;
8042         }
8043
8044         if (*r->out.count == 0) {
8045                 return WERR_NO_MORE_ITEMS;
8046         }
8047
8048         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8049                                                      spoolss_EnumForms,
8050                                                      *r->out.info, r->in.level,
8051                                                      *r->out.count);
8052         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8053         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8054
8055         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8056 }
8057
8058 /****************************************************************
8059  _spoolss_GetForm
8060 ****************************************************************/
8061
8062 WERROR _spoolss_GetForm(struct pipes_struct *p,
8063                         struct spoolss_GetForm *r)
8064 {
8065         WERROR result;
8066
8067         /* that's an [in out] buffer */
8068
8069         if (!r->in.buffer && (r->in.offered != 0)) {
8070                 TALLOC_FREE(r->out.info);
8071                 return WERR_INVALID_PARAMETER;
8072         }
8073
8074         DEBUG(4,("_spoolss_GetForm\n"));
8075         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8076         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
8077
8078         switch (r->in.level) {
8079         case 1:
8080                 result = winreg_printer_getform1_internal(p->mem_ctx,
8081                                                  get_session_info_system(),
8082                                                  p->msg_ctx,
8083                                                  r->in.form_name,
8084                                                  &r->out.info->info1);
8085                 break;
8086         default:
8087                 result = WERR_INVALID_LEVEL;
8088                 break;
8089         }
8090
8091         if (!W_ERROR_IS_OK(result)) {
8092                 TALLOC_FREE(r->out.info);
8093                 return result;
8094         }
8095
8096         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
8097                                                r->out.info, r->in.level);
8098         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8099
8100         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8101 }
8102
8103 /****************************************************************************
8104 ****************************************************************************/
8105
8106 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
8107                           struct spoolss_PortInfo1 *r,
8108                           const char *name)
8109 {
8110         r->port_name = talloc_strdup(mem_ctx, name);
8111         W_ERROR_HAVE_NO_MEMORY(r->port_name);
8112
8113         return WERR_OK;
8114 }
8115
8116 /****************************************************************************
8117  TODO: This probably needs distinguish between TCP/IP and Local ports
8118  somehow.
8119 ****************************************************************************/
8120
8121 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
8122                           struct spoolss_PortInfo2 *r,
8123                           const char *name)
8124 {
8125         r->port_name = talloc_strdup(mem_ctx, name);
8126         W_ERROR_HAVE_NO_MEMORY(r->port_name);
8127
8128         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
8129         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8130
8131         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
8132         W_ERROR_HAVE_NO_MEMORY(r->description);
8133
8134         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
8135         r->reserved = 0;
8136
8137         return WERR_OK;
8138 }
8139
8140
8141 /****************************************************************************
8142  wrapper around the enumer ports command
8143 ****************************************************************************/
8144
8145 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
8146 {
8147         char *cmd = lp_enumports_command(talloc_tos());
8148         char **qlines = NULL;
8149         char *command = NULL;
8150         int numlines;
8151         int ret;
8152         int fd;
8153
8154         *count = 0;
8155         *lines = NULL;
8156
8157         /* if no hook then just fill in the default port */
8158
8159         if ( !*cmd ) {
8160                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
8161                         return WERR_NOT_ENOUGH_MEMORY;
8162                 }
8163                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
8164                         TALLOC_FREE(qlines);
8165                         return WERR_NOT_ENOUGH_MEMORY;
8166                 }
8167                 qlines[1] = NULL;
8168                 numlines = 1;
8169         }
8170         else {
8171                 /* we have a valid enumport command */
8172
8173                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
8174                 if (!command) {
8175                         return WERR_NOT_ENOUGH_MEMORY;
8176                 }
8177
8178                 DEBUG(10,("Running [%s]\n", command));
8179                 ret = smbrun(command, &fd, NULL);
8180                 DEBUG(10,("Returned [%d]\n", ret));
8181                 TALLOC_FREE(command);
8182                 if (ret != 0) {
8183                         if (fd != -1) {
8184                                 close(fd);
8185                         }
8186                         return WERR_ACCESS_DENIED;
8187                 }
8188
8189                 numlines = 0;
8190                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
8191                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8192                 close(fd);
8193         }
8194
8195         *count = numlines;
8196         *lines = qlines;
8197
8198         return WERR_OK;
8199 }
8200
8201 /****************************************************************************
8202  enumports level 1.
8203 ****************************************************************************/
8204
8205 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8206                                 union spoolss_PortInfo **info_p,
8207                                 uint32_t *count)
8208 {
8209         union spoolss_PortInfo *info = NULL;
8210         int i=0;
8211         WERROR result = WERR_OK;
8212         char **qlines = NULL;
8213         int numlines = 0;
8214
8215         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8216         if (!W_ERROR_IS_OK(result)) {
8217                 goto out;
8218         }
8219
8220         if (numlines) {
8221                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8222                 if (!info) {
8223                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8224                         result = WERR_NOT_ENOUGH_MEMORY;
8225                         goto out;
8226                 }
8227
8228                 for (i=0; i<numlines; i++) {
8229                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8230                         result = fill_port_1(info, &info[i].info1, qlines[i]);
8231                         if (!W_ERROR_IS_OK(result)) {
8232                                 goto out;
8233                         }
8234                 }
8235         }
8236         TALLOC_FREE(qlines);
8237
8238 out:
8239         if (!W_ERROR_IS_OK(result)) {
8240                 TALLOC_FREE(info);
8241                 TALLOC_FREE(qlines);
8242                 *count = 0;
8243                 *info_p = NULL;
8244                 return result;
8245         }
8246
8247         *info_p = info;
8248         *count = numlines;
8249
8250         return WERR_OK;
8251 }
8252
8253 /****************************************************************************
8254  enumports level 2.
8255 ****************************************************************************/
8256
8257 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8258                                 union spoolss_PortInfo **info_p,
8259                                 uint32_t *count)
8260 {
8261         union spoolss_PortInfo *info = NULL;
8262         int i=0;
8263         WERROR result = WERR_OK;
8264         char **qlines = NULL;
8265         int numlines = 0;
8266
8267         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8268         if (!W_ERROR_IS_OK(result)) {
8269                 goto out;
8270         }
8271
8272         if (numlines) {
8273                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8274                 if (!info) {
8275                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8276                         result = WERR_NOT_ENOUGH_MEMORY;
8277                         goto out;
8278                 }
8279
8280                 for (i=0; i<numlines; i++) {
8281                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8282                         result = fill_port_2(info, &info[i].info2, qlines[i]);
8283                         if (!W_ERROR_IS_OK(result)) {
8284                                 goto out;
8285                         }
8286                 }
8287         }
8288         TALLOC_FREE(qlines);
8289
8290 out:
8291         if (!W_ERROR_IS_OK(result)) {
8292                 TALLOC_FREE(info);
8293                 TALLOC_FREE(qlines);
8294                 *count = 0;
8295                 *info_p = NULL;
8296                 return result;
8297         }
8298
8299         *info_p = info;
8300         *count = numlines;
8301
8302         return WERR_OK;
8303 }
8304
8305 /****************************************************************
8306  _spoolss_EnumPorts
8307 ****************************************************************/
8308
8309 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8310                           struct spoolss_EnumPorts *r)
8311 {
8312         WERROR result;
8313
8314         /* that's an [in out] buffer */
8315
8316         if (!r->in.buffer && (r->in.offered != 0)) {
8317                 return WERR_INVALID_PARAMETER;
8318         }
8319
8320         DEBUG(4,("_spoolss_EnumPorts\n"));
8321
8322         *r->out.count = 0;
8323         *r->out.needed = 0;
8324         *r->out.info = NULL;
8325
8326         switch (r->in.level) {
8327         case 1:
8328                 result = enumports_level_1(p->mem_ctx, r->out.info,
8329                                            r->out.count);
8330                 break;
8331         case 2:
8332                 result = enumports_level_2(p->mem_ctx, r->out.info,
8333                                            r->out.count);
8334                 break;
8335         default:
8336                 return WERR_INVALID_LEVEL;
8337         }
8338
8339         if (!W_ERROR_IS_OK(result)) {
8340                 return result;
8341         }
8342
8343         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8344                                                      spoolss_EnumPorts,
8345                                                      *r->out.info, r->in.level,
8346                                                      *r->out.count);
8347         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8348         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8349
8350         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8351 }
8352
8353 /****************************************************************************
8354 ****************************************************************************/
8355
8356 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8357                                            const char *server,
8358                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8359                                            struct spoolss_DeviceMode *devmode,
8360                                            struct security_descriptor *secdesc,
8361                                            struct spoolss_UserLevelCtr *user_ctr,
8362                                            struct policy_handle *handle)
8363 {
8364         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8365         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8366         int     snum;
8367         WERROR err = WERR_OK;
8368
8369         /* samba does not have a concept of local, non-shared printers yet, so
8370          * make sure we always setup sharename - gd */
8371         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8372             (info2->printername != NULL && info2->printername[0] != '\0')) {
8373                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8374                         "no sharename has been set, setting printername %s as sharename\n",
8375                         info2->printername));
8376                 info2->sharename = info2->printername;
8377         }
8378
8379         /* check to see if the printer already exists */
8380         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8381                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8382                         info2->sharename));
8383                 return WERR_PRINTER_ALREADY_EXISTS;
8384         }
8385
8386         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8387                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8388                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8389                                 info2->printername));
8390                         return WERR_PRINTER_ALREADY_EXISTS;
8391                 }
8392         }
8393
8394         /* validate printer info struct */
8395         if (!info2->printername || strlen(info2->printername) == 0) {
8396                 return WERR_INVALID_PRINTER_NAME;
8397         }
8398         if (!info2->portname || strlen(info2->portname) == 0) {
8399                 return WERR_UNKNOWN_PORT;
8400         }
8401         if (!info2->drivername || strlen(info2->drivername) == 0) {
8402                 return WERR_UNKNOWN_PRINTER_DRIVER;
8403         }
8404         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8405                 return WERR_UNKNOWN_PRINTPROCESSOR;
8406         }
8407
8408         /* FIXME!!!  smbd should check to see if the driver is installed before
8409            trying to add a printer like this  --jerry */
8410
8411         if (*lp_addprinter_command(talloc_tos()) ) {
8412                 char *raddr;
8413
8414                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8415                                                          p->mem_ctx);
8416                 if (raddr == NULL) {
8417                         return WERR_NOT_ENOUGH_MEMORY;
8418                 }
8419
8420                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8421                                        info2, raddr,
8422                                        p->msg_ctx) ) {
8423                         return WERR_ACCESS_DENIED;
8424                 }
8425         } else {
8426                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8427                         "smb.conf parameter \"addprinter command\" is defined. This "
8428                         "parameter must exist for this call to succeed\n",
8429                         info2->sharename ));
8430         }
8431
8432         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8433                 return WERR_ACCESS_DENIED;
8434         }
8435
8436         /* you must be a printer admin to add a new printer */
8437         if (!W_ERROR_IS_OK(print_access_check(p->session_info,
8438                                               p->msg_ctx,
8439                                               snum,
8440                                               PRINTER_ACCESS_ADMINISTER))) {
8441                 return WERR_ACCESS_DENIED;
8442         }
8443
8444         /*
8445          * Do sanity check on the requested changes for Samba.
8446          */
8447
8448         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8449                 return WERR_INVALID_PARAMETER;
8450         }
8451
8452         if (devmode == NULL) {
8453                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8454         }
8455
8456         err = update_dsspooler(p->mem_ctx,
8457                                get_session_info_system(),
8458                                p->msg_ctx,
8459                                0,
8460                                info2,
8461                                NULL);
8462         if (!W_ERROR_IS_OK(err)) {
8463                 return err;
8464         }
8465
8466         err = winreg_update_printer_internal(p->mem_ctx,
8467                                     get_session_info_system(),
8468                                     p->msg_ctx,
8469                                     info2->sharename,
8470                                     info2_mask,
8471                                     info2,
8472                                     devmode,
8473                                     secdesc);
8474         if (!W_ERROR_IS_OK(err)) {
8475                 return err;
8476         }
8477
8478         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8479         if (!W_ERROR_IS_OK(err)) {
8480                 /* Handle open failed - remove addition. */
8481                 ZERO_STRUCTP(handle);
8482                 return err;
8483         }
8484
8485         return WERR_OK;
8486 }
8487
8488 /****************************************************************
8489  _spoolss_AddPrinterEx
8490 ****************************************************************/
8491
8492 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8493                              struct spoolss_AddPrinterEx *r)
8494 {
8495         switch (r->in.info_ctr->level) {
8496         case 1:
8497                 /* we don't handle yet */
8498                 /* but I know what to do ... */
8499                 return WERR_INVALID_LEVEL;
8500         case 2:
8501                 return spoolss_addprinterex_level_2(p, r->in.server,
8502                                                     r->in.info_ctr,
8503                                                     r->in.devmode_ctr->devmode,
8504                                                     r->in.secdesc_ctr->sd,
8505                                                     r->in.userlevel_ctr,
8506                                                     r->out.handle);
8507         default:
8508                 return WERR_INVALID_LEVEL;
8509         }
8510 }
8511
8512 /****************************************************************
8513  _spoolss_AddPrinter
8514 ****************************************************************/
8515
8516 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8517                            struct spoolss_AddPrinter *r)
8518 {
8519         struct spoolss_AddPrinterEx a;
8520         struct spoolss_UserLevelCtr userlevel_ctr;
8521
8522         ZERO_STRUCT(userlevel_ctr);
8523
8524         userlevel_ctr.level = 1;
8525
8526         a.in.server             = r->in.server;
8527         a.in.info_ctr           = r->in.info_ctr;
8528         a.in.devmode_ctr        = r->in.devmode_ctr;
8529         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8530         a.in.userlevel_ctr      = &userlevel_ctr;
8531         a.out.handle            = r->out.handle;
8532
8533         return _spoolss_AddPrinterEx(p, &a);
8534 }
8535
8536 /****************************************************************
8537  _spoolss_AddPrinterDriverEx
8538 ****************************************************************/
8539
8540 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8541                                    struct spoolss_AddPrinterDriverEx *r)
8542 {
8543         WERROR err = WERR_OK;
8544         const char *driver_name = NULL;
8545         const char *driver_directory = NULL;
8546         uint32_t version;
8547
8548         /*
8549          * we only support the semantics of AddPrinterDriver()
8550          * i.e. only copy files that are newer than existing ones
8551          */
8552
8553         if (r->in.flags == 0) {
8554                 return WERR_INVALID_PARAMETER;
8555         }
8556
8557         if (!(r->in.flags & APD_COPY_ALL_FILES) &&
8558             !(r->in.flags & APD_COPY_NEW_FILES)) {
8559                 return WERR_ACCESS_DENIED;
8560         }
8561
8562         /* FIXME */
8563         if (r->in.info_ctr->level != 3 &&
8564             r->in.info_ctr->level != 6 &&
8565             r->in.info_ctr->level != 8) {
8566                 DEBUG(0,("%s: level %d not yet implemented\n", __func__,
8567                         r->in.info_ctr->level));
8568                 return WERR_INVALID_LEVEL;
8569         }
8570
8571         DEBUG(5,("Cleaning driver's information\n"));
8572         err = clean_up_driver_struct(p->mem_ctx,
8573                                      p->session_info,
8574                                      r->in.info_ctr,
8575                                      r->in.flags,
8576                                      &driver_directory);
8577         if (!W_ERROR_IS_OK(err)) {
8578                 DBG_ERR("clean_up_driver_struct failed - %s\n",
8579                         win_errstr(err));
8580                 goto done;
8581         }
8582
8583         DEBUG(5,("Moving driver to final destination\n"));
8584         err = move_driver_to_download_area(p->session_info,
8585                                            r->in.info_ctr,
8586                                            driver_directory);
8587         if (!W_ERROR_IS_OK(err)) {
8588                 DBG_ERR("move_driver_to_download_area failed - %s\n",
8589                         win_errstr(err));
8590                 goto done;
8591         }
8592
8593         err = winreg_add_driver_internal(p->mem_ctx,
8594                                 get_session_info_system(),
8595                                 p->msg_ctx,
8596                                 r->in.info_ctr,
8597                                 &driver_name,
8598                                 &version);
8599         if (!W_ERROR_IS_OK(err)) {
8600                 DBG_ERR("winreg_add_driver_internal failed - %s\n",
8601                         win_errstr(err));
8602                 goto done;
8603         }
8604
8605         /*
8606          * I think this is where he DrvUpgradePrinter() hook would be
8607          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8608          * server.  Right now, we just need to send ourselves a message
8609          * to update each printer bound to this driver.   --jerry
8610          */
8611
8612         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8613                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8614                         __func__, driver_name));
8615         }
8616
8617 done:
8618         return err;
8619 }
8620
8621 /****************************************************************
8622  _spoolss_AddPrinterDriver
8623 ****************************************************************/
8624
8625 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8626                                  struct spoolss_AddPrinterDriver *r)
8627 {
8628         struct spoolss_AddPrinterDriverEx a;
8629
8630         switch (r->in.info_ctr->level) {
8631         case 2:
8632         case 3:
8633         case 4:
8634         case 5:
8635                 break;
8636         default:
8637                 return WERR_INVALID_LEVEL;
8638         }
8639
8640         a.in.servername         = r->in.servername;
8641         a.in.info_ctr           = r->in.info_ctr;
8642         a.in.flags              = APD_COPY_NEW_FILES;
8643
8644         return _spoolss_AddPrinterDriverEx(p, &a);
8645 }
8646
8647 /****************************************************************************
8648 ****************************************************************************/
8649
8650 struct _spoolss_paths {
8651         int type;
8652         const char *share;
8653         const char *dir;
8654 };
8655
8656 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8657
8658 static const struct _spoolss_paths spoolss_paths[]= {
8659         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8660         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8661 };
8662
8663 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8664                                           const char *servername,
8665                                           const char *environment,
8666                                           int component,
8667                                           char **path)
8668 {
8669         const char *pservername = NULL;
8670         const char *long_archi;
8671         const char *short_archi;
8672
8673         *path = NULL;
8674
8675         /* environment may be empty */
8676         if (environment && strlen(environment)) {
8677                 long_archi = environment;
8678         } else {
8679                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8680                                                   "spoolss", "architecture",
8681                                                   GLOBAL_SPOOLSS_ARCHITECTURE);
8682         }
8683
8684         /* servername may be empty */
8685         if (servername && strlen(servername)) {
8686                 pservername = canon_servername(servername);
8687
8688                 if (!is_myname_or_ipaddr(pservername)) {
8689                         return WERR_INVALID_PARAMETER;
8690                 }
8691         }
8692
8693         if (!(short_archi = get_short_archi(long_archi))) {
8694                 return WERR_INVALID_ENVIRONMENT;
8695         }
8696
8697         switch (component) {
8698         case SPOOLSS_PRTPROCS_PATH:
8699         case SPOOLSS_DRIVER_PATH:
8700                 if (pservername) {
8701                         *path = talloc_asprintf(mem_ctx,
8702                                         "\\\\%s\\%s\\%s",
8703                                         pservername,
8704                                         spoolss_paths[component].share,
8705                                         short_archi);
8706                 } else {
8707                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8708                                         SPOOLSS_DEFAULT_SERVER_PATH,
8709                                         spoolss_paths[component].dir,
8710                                         short_archi);
8711                 }
8712                 break;
8713         default:
8714                 return WERR_INVALID_PARAMETER;
8715         }
8716
8717         if (!*path) {
8718                 return WERR_NOT_ENOUGH_MEMORY;
8719         }
8720
8721         return WERR_OK;
8722 }
8723
8724 /****************************************************************************
8725 ****************************************************************************/
8726
8727 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8728                                           const char *servername,
8729                                           const char *environment,
8730                                           struct spoolss_DriverDirectoryInfo1 *r)
8731 {
8732         WERROR werr;
8733         char *path = NULL;
8734
8735         werr = compose_spoolss_server_path(mem_ctx,
8736                                            servername,
8737                                            environment,
8738                                            SPOOLSS_DRIVER_PATH,
8739                                            &path);
8740         if (!W_ERROR_IS_OK(werr)) {
8741                 return werr;
8742         }
8743
8744         DEBUG(4,("printer driver directory: [%s]\n", path));
8745
8746         r->directory_name = path;
8747
8748         return WERR_OK;
8749 }
8750
8751 /****************************************************************
8752  _spoolss_GetPrinterDriverDirectory
8753 ****************************************************************/
8754
8755 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8756                                           struct spoolss_GetPrinterDriverDirectory *r)
8757 {
8758         WERROR werror;
8759
8760         /* that's an [in out] buffer */
8761
8762         if (!r->in.buffer && (r->in.offered != 0)) {
8763                 TALLOC_FREE(r->out.info);
8764                 return WERR_INVALID_PARAMETER;
8765         }
8766
8767         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8768                 r->in.level));
8769
8770         *r->out.needed = 0;
8771
8772         /* r->in.level is ignored */
8773
8774         werror = getprinterdriverdir_level_1(p->mem_ctx,
8775                                              r->in.server,
8776                                              r->in.environment,
8777                                              &r->out.info->info1);
8778         if (!W_ERROR_IS_OK(werror)) {
8779                 TALLOC_FREE(r->out.info);
8780                 return werror;
8781         }
8782
8783         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8784                                                r->out.info, r->in.level);
8785         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8786
8787         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8788 }
8789
8790 /****************************************************************
8791  _spoolss_EnumPrinterData
8792 ****************************************************************/
8793
8794 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8795                                 struct spoolss_EnumPrinterData *r)
8796 {
8797         WERROR result;
8798         struct spoolss_EnumPrinterDataEx r2;
8799         uint32_t count;
8800         struct spoolss_PrinterEnumValues *info, *val = NULL;
8801         uint32_t needed;
8802
8803         r2.in.handle    = r->in.handle;
8804         r2.in.key_name  = "PrinterDriverData";
8805         r2.in.offered   = 0;
8806         r2.out.count    = &count;
8807         r2.out.info     = &info;
8808         r2.out.needed   = &needed;
8809
8810         result = _spoolss_EnumPrinterDataEx(p, &r2);
8811         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8812                 r2.in.offered = needed;
8813                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8814         }
8815         if (!W_ERROR_IS_OK(result)) {
8816                 return result;
8817         }
8818
8819         /*
8820          * The NT machine wants to know the biggest size of value and data
8821          *
8822          * cf: MSDN EnumPrinterData remark section
8823          */
8824
8825         if (!r->in.value_offered && !r->in.data_offered) {
8826                 uint32_t biggest_valuesize = 0;
8827                 uint32_t biggest_datasize = 0;
8828                 int i, name_length;
8829
8830                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8831
8832                 for (i=0; i<count; i++) {
8833
8834                         name_length = strlen(info[i].value_name);
8835                         if (strlen(info[i].value_name) > biggest_valuesize) {
8836                                 biggest_valuesize = name_length;
8837                         }
8838
8839                         if (info[i].data_length > biggest_datasize) {
8840                                 biggest_datasize = info[i].data_length;
8841                         }
8842
8843                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8844                                 biggest_datasize));
8845                 }
8846
8847                 /* the value is an UNICODE string but real_value_size is the length
8848                    in bytes including the trailing 0 */
8849
8850                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8851                 *r->out.data_needed  = biggest_datasize;
8852
8853                 DEBUG(6,("final values: [%d], [%d]\n",
8854                         *r->out.value_needed, *r->out.data_needed));
8855
8856                 return WERR_OK;
8857         }
8858
8859         if (r->in.enum_index < count) {
8860                 val = &info[r->in.enum_index];
8861         }
8862
8863         if (val == NULL) {
8864                 /* out_value should default to "" or else NT4 has
8865                    problems unmarshalling the response */
8866
8867                 if (r->in.value_offered) {
8868                         *r->out.value_needed = 1;
8869                         r->out.value_name = talloc_strdup(r, "");
8870                         if (!r->out.value_name) {
8871                                 return WERR_NOT_ENOUGH_MEMORY;
8872                         }
8873                 } else {
8874                         r->out.value_name = NULL;
8875                         *r->out.value_needed = 0;
8876                 }
8877
8878                 /* the data is counted in bytes */
8879
8880                 *r->out.data_needed = r->in.data_offered;
8881
8882                 result = WERR_NO_MORE_ITEMS;
8883         } else {
8884                 /*
8885                  * the value is:
8886                  * - counted in bytes in the request
8887                  * - counted in UNICODE chars in the max reply
8888                  * - counted in bytes in the real size
8889                  *
8890                  * take a pause *before* coding not *during* coding
8891                  */
8892
8893                 /* name */
8894                 if (r->in.value_offered) {
8895                         r->out.value_name = talloc_strdup(r, val->value_name);
8896                         if (!r->out.value_name) {
8897                                 return WERR_NOT_ENOUGH_MEMORY;
8898                         }
8899                         *r->out.value_needed = val->value_name_len;
8900                 } else {
8901                         r->out.value_name = NULL;
8902                         *r->out.value_needed = 0;
8903                 }
8904
8905                 /* type */
8906
8907                 *r->out.type = val->type;
8908
8909                 /* data - counted in bytes */
8910
8911                 /*
8912                  * See the section "Dynamically Typed Query Parameters"
8913                  * in MS-RPRN.
8914                  */
8915
8916                 if (r->out.data && val->data && val->data->data &&
8917                                 val->data_length && r->in.data_offered) {
8918                         memcpy(r->out.data, val->data->data,
8919                                 MIN(val->data_length,r->in.data_offered));
8920                 }
8921
8922                 *r->out.data_needed = val->data_length;
8923
8924                 result = WERR_OK;
8925         }
8926
8927         return result;
8928 }
8929
8930 /****************************************************************
8931  _spoolss_SetPrinterData
8932 ****************************************************************/
8933
8934 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8935                                struct spoolss_SetPrinterData *r)
8936 {
8937         struct spoolss_SetPrinterDataEx r2;
8938
8939         r2.in.handle            = r->in.handle;
8940         r2.in.key_name          = "PrinterDriverData";
8941         r2.in.value_name        = r->in.value_name;
8942         r2.in.type              = r->in.type;
8943         r2.in.data              = r->in.data;
8944         r2.in.offered           = r->in.offered;
8945
8946         return _spoolss_SetPrinterDataEx(p, &r2);
8947 }
8948
8949 /****************************************************************
8950  _spoolss_ResetPrinter
8951 ****************************************************************/
8952
8953 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8954                              struct spoolss_ResetPrinter *r)
8955 {
8956         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8957         int             snum;
8958
8959         DEBUG(5,("_spoolss_ResetPrinter\n"));
8960
8961         /*
8962          * All we do is to check to see if the handle and queue is valid.
8963          * This call really doesn't mean anything to us because we only
8964          * support RAW printing.   --jerry
8965          */
8966
8967         if (!Printer) {
8968                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8969                         OUR_HANDLE(r->in.handle)));
8970                 return WERR_INVALID_HANDLE;
8971         }
8972
8973         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8974                 return WERR_INVALID_HANDLE;
8975
8976
8977         /* blindly return success */
8978         return WERR_OK;
8979 }
8980
8981 /****************************************************************
8982  _spoolss_DeletePrinterData
8983 ****************************************************************/
8984
8985 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8986                                   struct spoolss_DeletePrinterData *r)
8987 {
8988         struct spoolss_DeletePrinterDataEx r2;
8989
8990         r2.in.handle            = r->in.handle;
8991         r2.in.key_name          = "PrinterDriverData";
8992         r2.in.value_name        = r->in.value_name;
8993
8994         return _spoolss_DeletePrinterDataEx(p, &r2);
8995 }
8996
8997 /****************************************************************
8998  _spoolss_AddForm
8999 ****************************************************************/
9000
9001 WERROR _spoolss_AddForm(struct pipes_struct *p,
9002                         struct spoolss_AddForm *r)
9003 {
9004         struct spoolss_AddFormInfo1 *form;
9005         int snum = -1;
9006         WERROR status = WERR_OK;
9007         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9008         struct dcerpc_binding_handle *b;
9009         TALLOC_CTX *tmp_ctx = NULL;
9010
9011         DEBUG(5,("_spoolss_AddForm\n"));
9012
9013         if (!Printer) {
9014                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
9015                         OUR_HANDLE(r->in.handle)));
9016                 return WERR_INVALID_HANDLE;
9017         }
9018
9019         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9020            and not a printer admin, then fail */
9021
9022         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9023             !security_token_has_privilege(p->session_info->security_token,
9024                                           SEC_PRIV_PRINT_OPERATOR)) {
9025                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
9026                 return WERR_ACCESS_DENIED;
9027         }
9028
9029         if (r->in.info_ctr->level != 1) {
9030                 return WERR_INVALID_LEVEL;
9031         }
9032
9033         form = r->in.info_ctr->info.info1;
9034         if (!form) {
9035                 return WERR_INVALID_PARAMETER;
9036         }
9037
9038         switch (form->flags) {
9039         case SPOOLSS_FORM_USER:
9040         case SPOOLSS_FORM_BUILTIN:
9041         case SPOOLSS_FORM_PRINTER:
9042                 break;
9043         default:
9044                 return WERR_INVALID_PARAMETER;
9045         }
9046
9047         tmp_ctx = talloc_new(p->mem_ctx);
9048         if (!tmp_ctx) {
9049                 return WERR_NOT_ENOUGH_MEMORY;
9050         }
9051
9052         status = winreg_printer_binding_handle(tmp_ctx,
9053                                                get_session_info_system(),
9054                                                p->msg_ctx,
9055                                                &b);
9056         if (!W_ERROR_IS_OK(status)) {
9057                 goto done;
9058         }
9059
9060         status = winreg_printer_addform1(tmp_ctx, b, form);
9061         if (!W_ERROR_IS_OK(status)) {
9062                 goto done;
9063         }
9064
9065         /*
9066          * ChangeID must always be set if this is a printer
9067          */
9068         if (Printer->printer_type == SPLHND_PRINTER) {
9069                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9070                         status = WERR_INVALID_HANDLE;
9071                         goto done;
9072                 }
9073
9074                 status = winreg_printer_update_changeid(tmp_ctx, b,
9075                                                         lp_const_servicename(snum));
9076         }
9077
9078 done:
9079         talloc_free(tmp_ctx);
9080         return status;
9081 }
9082
9083 /****************************************************************
9084  _spoolss_DeleteForm
9085 ****************************************************************/
9086
9087 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
9088                            struct spoolss_DeleteForm *r)
9089 {
9090         const char *form_name = r->in.form_name;
9091         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9092         int snum = -1;
9093         WERROR status = WERR_OK;
9094         struct dcerpc_binding_handle *b;
9095         TALLOC_CTX *tmp_ctx = NULL;
9096
9097         DEBUG(5,("_spoolss_DeleteForm\n"));
9098
9099         if (!Printer) {
9100                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
9101                         OUR_HANDLE(r->in.handle)));
9102                 return WERR_INVALID_HANDLE;
9103         }
9104
9105         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9106             !security_token_has_privilege(p->session_info->security_token,
9107                                           SEC_PRIV_PRINT_OPERATOR)) {
9108                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
9109                 return WERR_ACCESS_DENIED;
9110         }
9111
9112         tmp_ctx = talloc_new(p->mem_ctx);
9113         if (!tmp_ctx) {
9114                 return WERR_NOT_ENOUGH_MEMORY;
9115         }
9116
9117         status = winreg_printer_binding_handle(tmp_ctx,
9118                                                get_session_info_system(),
9119                                                p->msg_ctx,
9120                                                &b);
9121         if (!W_ERROR_IS_OK(status)) {
9122                 goto done;
9123         }
9124
9125         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
9126         if (!W_ERROR_IS_OK(status)) {
9127                 goto done;
9128         }
9129
9130         /*
9131          * ChangeID must always be set if this is a printer
9132          */
9133         if (Printer->printer_type == SPLHND_PRINTER) {
9134                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9135                         status = WERR_INVALID_HANDLE;
9136                         goto done;
9137                 }
9138
9139                 status = winreg_printer_update_changeid(tmp_ctx, b,
9140                                                         lp_const_servicename(snum));
9141         }
9142
9143 done:
9144         talloc_free(tmp_ctx);
9145         return status;
9146 }
9147
9148 /****************************************************************
9149  _spoolss_SetForm
9150 ****************************************************************/
9151
9152 WERROR _spoolss_SetForm(struct pipes_struct *p,
9153                         struct spoolss_SetForm *r)
9154 {
9155         struct spoolss_AddFormInfo1 *form;
9156         const char *form_name = r->in.form_name;
9157         int snum = -1;
9158         WERROR status = WERR_OK;
9159         struct dcerpc_binding_handle *b;
9160         TALLOC_CTX *tmp_ctx = NULL;
9161
9162         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9163
9164         DEBUG(5,("_spoolss_SetForm\n"));
9165
9166         if (!Printer) {
9167                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
9168                         OUR_HANDLE(r->in.handle)));
9169                 return WERR_INVALID_HANDLE;
9170         }
9171
9172         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9173            and not a printer admin, then fail */
9174
9175         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9176              !security_token_has_privilege(p->session_info->security_token,
9177                                            SEC_PRIV_PRINT_OPERATOR)) {
9178                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
9179                 return WERR_ACCESS_DENIED;
9180         }
9181
9182         if (r->in.info_ctr->level != 1) {
9183                 return WERR_INVALID_LEVEL;
9184         }
9185
9186         form = r->in.info_ctr->info.info1;
9187         if (!form) {
9188                 return WERR_INVALID_PARAMETER;
9189         }
9190
9191         tmp_ctx = talloc_new(p->mem_ctx);
9192         if (!tmp_ctx) {
9193                 return WERR_NOT_ENOUGH_MEMORY;
9194         }
9195
9196         status = winreg_printer_binding_handle(tmp_ctx,
9197                                                get_session_info_system(),
9198                                                p->msg_ctx,
9199                                                &b);
9200         if (!W_ERROR_IS_OK(status)) {
9201                 goto done;
9202         }
9203
9204         status = winreg_printer_setform1(tmp_ctx, b,
9205                                          form_name,
9206                                          form);
9207         if (!W_ERROR_IS_OK(status)) {
9208                 goto done;
9209         }
9210
9211         /*
9212          * ChangeID must always be set if this is a printer
9213          */
9214         if (Printer->printer_type == SPLHND_PRINTER) {
9215                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9216                         status = WERR_INVALID_HANDLE;
9217                         goto done;
9218                 }
9219
9220                 status = winreg_printer_update_changeid(tmp_ctx, b,
9221                                                         lp_const_servicename(snum));
9222         }
9223
9224 done:
9225         talloc_free(tmp_ctx);
9226         return status;
9227 }
9228
9229 /****************************************************************************
9230  fill_print_processor1
9231 ****************************************************************************/
9232
9233 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9234                                     struct spoolss_PrintProcessorInfo1 *r,
9235                                     const char *print_processor_name)
9236 {
9237         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9238         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9239
9240         return WERR_OK;
9241 }
9242
9243 /****************************************************************************
9244  enumprintprocessors level 1.
9245 ****************************************************************************/
9246
9247 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9248                                           union spoolss_PrintProcessorInfo **info_p,
9249                                           uint32_t *count)
9250 {
9251         union spoolss_PrintProcessorInfo *info;
9252         WERROR result;
9253
9254         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9255         W_ERROR_HAVE_NO_MEMORY(info);
9256
9257         *count = 1;
9258
9259         result = fill_print_processor1(info, &info[0].info1, "winprint");
9260         if (!W_ERROR_IS_OK(result)) {
9261                 goto out;
9262         }
9263
9264  out:
9265         if (!W_ERROR_IS_OK(result)) {
9266                 TALLOC_FREE(info);
9267                 *count = 0;
9268                 return result;
9269         }
9270
9271         *info_p = info;
9272
9273         return WERR_OK;
9274 }
9275
9276 /****************************************************************
9277  _spoolss_EnumPrintProcessors
9278 ****************************************************************/
9279
9280 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9281                                     struct spoolss_EnumPrintProcessors *r)
9282 {
9283         WERROR result;
9284
9285         /* that's an [in out] buffer */
9286
9287         if (!r->in.buffer && (r->in.offered != 0)) {
9288                 return WERR_INVALID_PARAMETER;
9289         }
9290
9291         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9292
9293         /*
9294          * Enumerate the print processors ...
9295          *
9296          * Just reply with "winprint", to keep NT happy
9297          * and I can use my nice printer checker.
9298          */
9299
9300         *r->out.count = 0;
9301         *r->out.needed = 0;
9302         *r->out.info = NULL;
9303
9304         if (!get_short_archi(r->in.environment)) {
9305                 return WERR_INVALID_ENVIRONMENT;
9306         }
9307
9308         switch (r->in.level) {
9309         case 1:
9310                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9311                                                      r->out.count);
9312                 break;
9313         default:
9314                 return WERR_INVALID_LEVEL;
9315         }
9316
9317         if (!W_ERROR_IS_OK(result)) {
9318                 return result;
9319         }
9320
9321         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9322                                                      spoolss_EnumPrintProcessors,
9323                                                      *r->out.info, r->in.level,
9324                                                      *r->out.count);
9325         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9326         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9327
9328         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9329 }
9330
9331 /****************************************************************************
9332  fill_printprocdatatype1
9333 ****************************************************************************/
9334
9335 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9336                                       struct spoolss_PrintProcDataTypesInfo1 *r,
9337                                       const char *name_array)
9338 {
9339         r->name_array = talloc_strdup(mem_ctx, name_array);
9340         W_ERROR_HAVE_NO_MEMORY(r->name_array);
9341
9342         return WERR_OK;
9343 }
9344
9345 /****************************************************************************
9346  enumprintprocdatatypes level 1.
9347 ****************************************************************************/
9348
9349 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9350                                              union spoolss_PrintProcDataTypesInfo **info_p,
9351                                              uint32_t *count)
9352 {
9353         WERROR result;
9354         union spoolss_PrintProcDataTypesInfo *info;
9355
9356         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9357         W_ERROR_HAVE_NO_MEMORY(info);
9358
9359         *count = 1;
9360
9361         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9362         if (!W_ERROR_IS_OK(result)) {
9363                 goto out;
9364         }
9365
9366  out:
9367         if (!W_ERROR_IS_OK(result)) {
9368                 TALLOC_FREE(info);
9369                 *count = 0;
9370                 return result;
9371         }
9372
9373         *info_p = info;
9374
9375         return WERR_OK;
9376 }
9377
9378 /****************************************************************
9379  _spoolss_EnumPrintProcessorDataTypes
9380 ****************************************************************/
9381
9382 WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
9383                                             struct spoolss_EnumPrintProcessorDataTypes *r)
9384 {
9385         WERROR result;
9386
9387         /* that's an [in out] buffer */
9388
9389         if (!r->in.buffer && (r->in.offered != 0)) {
9390                 return WERR_INVALID_PARAMETER;
9391         }
9392
9393         DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
9394
9395         *r->out.count = 0;
9396         *r->out.needed = 0;
9397         *r->out.info = NULL;
9398
9399         if (r->in.print_processor_name == NULL ||
9400             !strequal(r->in.print_processor_name, "winprint")) {
9401                 return WERR_UNKNOWN_PRINTPROCESSOR;
9402         }
9403
9404         switch (r->in.level) {
9405         case 1:
9406                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9407                                                         r->out.count);
9408                 break;
9409         default:
9410                 return WERR_INVALID_LEVEL;
9411         }
9412
9413         if (!W_ERROR_IS_OK(result)) {
9414                 return result;
9415         }
9416
9417         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9418                                                      spoolss_EnumPrintProcessorDataTypes,
9419                                                      *r->out.info, r->in.level,
9420                                                      *r->out.count);
9421         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9422         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9423
9424         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9425 }
9426
9427 /****************************************************************************
9428  fill_monitor_1
9429 ****************************************************************************/
9430
9431 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9432                              struct spoolss_MonitorInfo1 *r,
9433                              const char *monitor_name)
9434 {
9435         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9436         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9437
9438         return WERR_OK;
9439 }
9440
9441 /****************************************************************************
9442  fill_monitor_2
9443 ****************************************************************************/
9444
9445 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9446                              struct spoolss_MonitorInfo2 *r,
9447                              const char *monitor_name,
9448                              const char *environment,
9449                              const char *dll_name)
9450 {
9451         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9452         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9453         r->environment                  = talloc_strdup(mem_ctx, environment);
9454         W_ERROR_HAVE_NO_MEMORY(r->environment);
9455         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9456         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9457
9458         return WERR_OK;
9459 }
9460
9461 /****************************************************************************
9462  enumprintmonitors level 1.
9463 ****************************************************************************/
9464
9465 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9466                                         union spoolss_MonitorInfo **info_p,
9467                                         uint32_t *count)
9468 {
9469         union spoolss_MonitorInfo *info;
9470         WERROR result = WERR_OK;
9471
9472         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9473         W_ERROR_HAVE_NO_MEMORY(info);
9474
9475         *count = 2;
9476
9477         result = fill_monitor_1(info, &info[0].info1,
9478                                 SPL_LOCAL_PORT);
9479         if (!W_ERROR_IS_OK(result)) {
9480                 goto out;
9481         }
9482
9483         result = fill_monitor_1(info, &info[1].info1,
9484                                 SPL_TCPIP_PORT);
9485         if (!W_ERROR_IS_OK(result)) {
9486                 goto out;
9487         }
9488
9489 out:
9490         if (!W_ERROR_IS_OK(result)) {
9491                 TALLOC_FREE(info);
9492                 *count = 0;
9493                 return result;
9494         }
9495
9496         *info_p = info;
9497
9498         return WERR_OK;
9499 }
9500
9501 /****************************************************************************
9502  enumprintmonitors level 2.
9503 ****************************************************************************/
9504
9505 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9506                                         union spoolss_MonitorInfo **info_p,
9507                                         uint32_t *count)
9508 {
9509         union spoolss_MonitorInfo *info;
9510         WERROR result = WERR_OK;
9511         const char *architecture;
9512
9513         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9514         W_ERROR_HAVE_NO_MEMORY(info);
9515
9516         *count = 2;
9517
9518         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
9519                                             "spoolss",
9520                                             "architecture",
9521                                             GLOBAL_SPOOLSS_ARCHITECTURE);
9522
9523         result = fill_monitor_2(info, &info[0].info2,
9524                                 SPL_LOCAL_PORT,
9525                                 architecture,
9526                                 "localmon.dll");
9527         if (!W_ERROR_IS_OK(result)) {
9528                 goto out;
9529         }
9530
9531         result = fill_monitor_2(info, &info[1].info2,
9532                                 SPL_TCPIP_PORT,
9533                                 architecture,
9534                                 "tcpmon.dll");
9535         if (!W_ERROR_IS_OK(result)) {
9536                 goto out;
9537         }
9538
9539 out:
9540         if (!W_ERROR_IS_OK(result)) {
9541                 TALLOC_FREE(info);
9542                 *count = 0;
9543                 return result;
9544         }
9545
9546         *info_p = info;
9547
9548         return WERR_OK;
9549 }
9550
9551 /****************************************************************
9552  _spoolss_EnumMonitors
9553 ****************************************************************/
9554
9555 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9556                              struct spoolss_EnumMonitors *r)
9557 {
9558         WERROR result;
9559
9560         /* that's an [in out] buffer */
9561
9562         if (!r->in.buffer && (r->in.offered != 0)) {
9563                 return WERR_INVALID_PARAMETER;
9564         }
9565
9566         DEBUG(5,("_spoolss_EnumMonitors\n"));
9567
9568         /*
9569          * Enumerate the print monitors ...
9570          *
9571          * Just reply with "Local Port", to keep NT happy
9572          * and I can use my nice printer checker.
9573          */
9574
9575         *r->out.count = 0;
9576         *r->out.needed = 0;
9577         *r->out.info = NULL;
9578
9579         switch (r->in.level) {
9580         case 1:
9581                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9582                                                    r->out.count);
9583                 break;
9584         case 2:
9585                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9586                                                    r->out.count);
9587                 break;
9588         default:
9589                 return WERR_INVALID_LEVEL;
9590         }
9591
9592         if (!W_ERROR_IS_OK(result)) {
9593                 return result;
9594         }
9595
9596         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9597                                                      spoolss_EnumMonitors,
9598                                                      *r->out.info, r->in.level,
9599                                                      *r->out.count);
9600         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9601         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9602
9603         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9604 }
9605
9606 /****************************************************************************
9607 ****************************************************************************/
9608
9609 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9610                              const print_queue_struct *queue,
9611                              int count, int snum,
9612                              struct spoolss_PrinterInfo2 *pinfo2,
9613                              uint32_t jobid,
9614                              int sysjob,
9615                              struct spoolss_JobInfo1 *r)
9616 {
9617         int i = 0;
9618         bool found = false;
9619
9620         for (i=0; i<count; i++) {
9621                 if (queue[i].sysjob == sysjob) {
9622                         found = true;
9623                         break;
9624                 }
9625         }
9626
9627         if (found == false) {
9628                 /* NT treats not found as bad param... yet another bad choice */
9629                 return WERR_INVALID_PARAMETER;
9630         }
9631
9632         return fill_job_info1(mem_ctx,
9633                               r,
9634                               &queue[i],
9635                               jobid,
9636                               i,
9637                               snum,
9638                               pinfo2);
9639 }
9640
9641 /****************************************************************************
9642 ****************************************************************************/
9643
9644 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9645                              const print_queue_struct *queue,
9646                              int count, int snum,
9647                              struct spoolss_PrinterInfo2 *pinfo2,
9648                              uint32_t jobid,
9649                              int sysjob,
9650                              struct spoolss_JobInfo2 *r)
9651 {
9652         int i = 0;
9653         bool found = false;
9654         struct spoolss_DeviceMode *devmode;
9655         WERROR result;
9656
9657         for (i=0; i<count; i++) {
9658                 if (queue[i].sysjob == sysjob) {
9659                         found = true;
9660                         break;
9661                 }
9662         }
9663
9664         if (found == false) {
9665                 /* NT treats not found as bad param... yet another bad
9666                    choice */
9667                 return WERR_INVALID_PARAMETER;
9668         }
9669
9670         /*
9671          * if the print job does not have a DEVMODE associated with it,
9672          * just use the one for the printer. A NULL devicemode is not
9673          *  a failure condition
9674          */
9675
9676         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9677         if (!devmode) {
9678                 result = spoolss_create_default_devmode(mem_ctx,
9679                                                 pinfo2->printername,
9680                                                 &devmode);
9681                 if (!W_ERROR_IS_OK(result)) {
9682                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9683                         return result;
9684                 }
9685         }
9686
9687         return fill_job_info2(mem_ctx,
9688                               r,
9689                               &queue[i],
9690                               jobid,
9691                               i,
9692                               snum,
9693                               pinfo2,
9694                               devmode);
9695 }
9696
9697 /****************************************************************
9698  _spoolss_GetJob
9699 ****************************************************************/
9700
9701 WERROR _spoolss_GetJob(struct pipes_struct *p,
9702                        struct spoolss_GetJob *r)
9703 {
9704         WERROR result = WERR_OK;
9705         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9706         const char *svc_name;
9707         int sysjob;
9708         int snum;
9709         int count;
9710         struct tdb_print_db *pdb;
9711         print_queue_struct      *queue = NULL;
9712         print_status_struct prt_status;
9713
9714         /* that's an [in out] buffer */
9715
9716         if (!r->in.buffer && (r->in.offered != 0)) {
9717                 result = WERR_INVALID_PARAMETER;
9718                 goto err_jinfo_free;
9719         }
9720
9721         DEBUG(5,("_spoolss_GetJob\n"));
9722
9723         *r->out.needed = 0;
9724
9725         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9726                 result = WERR_INVALID_HANDLE;
9727                 goto err_jinfo_free;
9728         }
9729
9730         svc_name = lp_const_servicename(snum);
9731         if (svc_name == NULL) {
9732                 result = WERR_INVALID_PARAMETER;
9733                 goto err_jinfo_free;
9734         }
9735
9736         result = winreg_get_printer_internal(p->mem_ctx,
9737                                     get_session_info_system(),
9738                                     p->msg_ctx,
9739                                     svc_name,
9740                                     &pinfo2);
9741         if (!W_ERROR_IS_OK(result)) {
9742                 goto err_jinfo_free;
9743         }
9744
9745         pdb = get_print_db_byname(svc_name);
9746         if (pdb == NULL) {
9747                 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9748                 result = WERR_INVALID_PARAMETER;
9749                 goto err_pinfo_free;
9750         }
9751
9752         sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9753         release_print_db(pdb);
9754         if (sysjob == -1) {
9755                 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9756                 result = WERR_INVALID_PARAMETER;
9757                 goto err_pinfo_free;
9758         }
9759
9760         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9761
9762         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9763                      count, prt_status.status, prt_status.message));
9764
9765         switch (r->in.level) {
9766         case 1:
9767                 result = getjob_level_1(p->mem_ctx,
9768                                         queue, count, snum, pinfo2,
9769                                         r->in.job_id, sysjob,
9770                                         &r->out.info->info1);
9771                 break;
9772         case 2:
9773                 result = getjob_level_2(p->mem_ctx,
9774                                         queue, count, snum, pinfo2,
9775                                         r->in.job_id, sysjob,
9776                                         &r->out.info->info2);
9777                 break;
9778         default:
9779                 result = WERR_INVALID_LEVEL;
9780                 break;
9781         }
9782
9783         SAFE_FREE(queue);
9784         TALLOC_FREE(pinfo2);
9785
9786         if (!W_ERROR_IS_OK(result)) {
9787                 goto err_jinfo_free;
9788         }
9789
9790         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9791                                                                                    r->in.level);
9792         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9793
9794         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9795
9796 err_pinfo_free:
9797         TALLOC_FREE(pinfo2);
9798 err_jinfo_free:
9799         TALLOC_FREE(r->out.info);
9800         return result;
9801 }
9802
9803 /****************************************************************
9804  _spoolss_GetPrinterDataEx
9805 ****************************************************************/
9806
9807 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9808                                  struct spoolss_GetPrinterDataEx *r)
9809 {
9810
9811         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9812         const char *printer;
9813         int                     snum = 0;
9814         WERROR result = WERR_OK;
9815         DATA_BLOB blob;
9816         enum winreg_Type val_type = REG_NONE;
9817         uint8_t *val_data = NULL;
9818         uint32_t val_size = 0;
9819         struct dcerpc_binding_handle *b;
9820         TALLOC_CTX *tmp_ctx;
9821
9822         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9823
9824         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9825                 r->in.key_name, r->in.value_name));
9826
9827         /* in case of problem, return some default values */
9828
9829         *r->out.needed  = 0;
9830         *r->out.type    = REG_NONE;
9831
9832         tmp_ctx = talloc_new(p->mem_ctx);
9833         if (!tmp_ctx) {
9834                 return WERR_NOT_ENOUGH_MEMORY;
9835         }
9836
9837         if (!Printer) {
9838                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9839                         OUR_HANDLE(r->in.handle)));
9840                 result = WERR_INVALID_HANDLE;
9841                 goto done;
9842         }
9843
9844         /* Is the handle to a printer or to the server? */
9845
9846         if (Printer->printer_type == SPLHND_SERVER) {
9847
9848                 union spoolss_PrinterData data;
9849
9850                 result = getprinterdata_printer_server(tmp_ctx,
9851                                                        r->in.value_name,
9852                                                        r->out.type,
9853                                                        &data);
9854                 if (!W_ERROR_IS_OK(result)) {
9855                         goto done;
9856                 }
9857
9858                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9859                                                   *r->out.type, &data);
9860                 if (!W_ERROR_IS_OK(result)) {
9861                         goto done;
9862                 }
9863
9864                 *r->out.needed = blob.length;
9865
9866                 if (r->in.offered >= *r->out.needed) {
9867                         memcpy(r->out.data, blob.data, blob.length);
9868                 }
9869
9870                 result = WERR_OK;
9871                 goto done;
9872         }
9873
9874         /* check to see if the keyname is valid */
9875         if (!strlen(r->in.key_name)) {
9876                 result = WERR_INVALID_PARAMETER;
9877                 goto done;
9878         }
9879
9880         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9881                 result = WERR_INVALID_HANDLE;
9882                 goto done;
9883         }
9884         printer = lp_const_servicename(snum);
9885
9886         result = winreg_printer_binding_handle(tmp_ctx,
9887                                                get_session_info_system(),
9888                                                p->msg_ctx,
9889                                                &b);
9890         if (!W_ERROR_IS_OK(result)) {
9891                 goto done;
9892         }
9893
9894         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9895         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9896             strequal(r->in.value_name, "ChangeId")) {
9897                 *r->out.type = REG_DWORD;
9898                 *r->out.needed = 4;
9899                 if (r->in.offered >= *r->out.needed) {
9900                         uint32_t changeid = 0;
9901
9902                         result = winreg_printer_get_changeid(tmp_ctx, b,
9903                                                              printer,
9904                                                              &changeid);
9905                         if (!W_ERROR_IS_OK(result)) {
9906                                 goto done;
9907                         }
9908
9909                         SIVAL(r->out.data, 0, changeid);
9910                         result = WERR_OK;
9911                 }
9912                 goto done;
9913         }
9914
9915         result = winreg_get_printer_dataex(tmp_ctx, b,
9916                                            printer,
9917                                            r->in.key_name,
9918                                            r->in.value_name,
9919                                            &val_type,
9920                                            &val_data,
9921                                            &val_size);
9922         if (!W_ERROR_IS_OK(result)) {
9923                 goto done;
9924         }
9925
9926         *r->out.needed = val_size;
9927         *r->out.type = val_type;
9928
9929         if (r->in.offered >= *r->out.needed) {
9930                 memcpy(r->out.data, val_data, val_size);
9931         }
9932
9933 done:
9934         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9935
9936         if (W_ERROR_IS_OK(result)) {
9937                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9938         }
9939
9940         talloc_free(tmp_ctx);
9941         return result;
9942 }
9943
9944 /****************************************************************
9945  _spoolss_SetPrinterDataEx
9946 ****************************************************************/
9947
9948 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9949                                  struct spoolss_SetPrinterDataEx *r)
9950 {
9951         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9952         int                     snum = 0;
9953         WERROR                  result = WERR_OK;
9954         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9955         char                    *oid_string;
9956         struct dcerpc_binding_handle *b;
9957         TALLOC_CTX *tmp_ctx;
9958
9959         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9960
9961         /* From MSDN documentation of SetPrinterDataEx: pass request to
9962            SetPrinterData if key is "PrinterDriverData" */
9963
9964         if (!Printer) {
9965                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9966                         OUR_HANDLE(r->in.handle)));
9967                 return WERR_INVALID_HANDLE;
9968         }
9969
9970         if (Printer->printer_type == SPLHND_SERVER) {
9971                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9972                         "Not implemented for server handles yet\n"));
9973                 return WERR_INVALID_PARAMETER;
9974         }
9975
9976         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9977                 return WERR_INVALID_HANDLE;
9978         }
9979
9980         /*
9981          * Access check : NT returns "access denied" if you make a
9982          * SetPrinterData call without the necessary privildge.
9983          * we were originally returning OK if nothing changed
9984          * which made Win2k issue **a lot** of SetPrinterData
9985          * when connecting to a printer  --jerry
9986          */
9987
9988         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9989                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9990                         "change denied by handle access permissions\n"));
9991                 return WERR_ACCESS_DENIED;
9992         }
9993
9994         tmp_ctx = talloc_new(p->mem_ctx);
9995         if (!tmp_ctx) {
9996                 return WERR_NOT_ENOUGH_MEMORY;
9997         }
9998
9999         result = winreg_printer_binding_handle(tmp_ctx,
10000                                                get_session_info_system(),
10001                                                p->msg_ctx,
10002                                                &b);
10003         if (!W_ERROR_IS_OK(result)) {
10004                 goto done;
10005         }
10006
10007         result = winreg_get_printer(tmp_ctx, b,
10008                                     lp_servicename(talloc_tos(), snum),
10009                                     &pinfo2);
10010         if (!W_ERROR_IS_OK(result)) {
10011                 goto done;
10012         }
10013
10014         /* check for OID in valuename */
10015
10016         oid_string = strchr(r->in.value_name, ',');
10017         if (oid_string) {
10018                 *oid_string = '\0';
10019                 oid_string++;
10020         }
10021
10022         /* save the registry data */
10023
10024         result = winreg_set_printer_dataex(tmp_ctx, b,
10025                                            pinfo2->sharename,
10026                                            r->in.key_name,
10027                                            r->in.value_name,
10028                                            r->in.type,
10029                                            r->in.data,
10030                                            r->in.offered);
10031
10032         if (W_ERROR_IS_OK(result)) {
10033                 /* save the OID if one was specified */
10034                 if (oid_string) {
10035                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
10036                                 r->in.key_name, SPOOL_OID_KEY);
10037                         if (!str) {
10038                                 result = WERR_NOT_ENOUGH_MEMORY;
10039                                 goto done;
10040                         }
10041
10042                         /*
10043                          * I'm not checking the status here on purpose.  Don't know
10044                          * if this is right, but I'm returning the status from the
10045                          * previous set_printer_dataex() call.  I have no idea if
10046                          * this is right.    --jerry
10047                          */
10048                         winreg_set_printer_dataex(tmp_ctx, b,
10049                                                   pinfo2->sharename,
10050                                                   str,
10051                                                   r->in.value_name,
10052                                                   REG_SZ,
10053                                                   (uint8_t *) oid_string,
10054                                                   strlen(oid_string) + 1);
10055                 }
10056
10057                 result = winreg_printer_update_changeid(tmp_ctx, b,
10058                                                         lp_const_servicename(snum));
10059
10060         }
10061
10062 done:
10063         talloc_free(tmp_ctx);
10064         return result;
10065 }
10066
10067 /****************************************************************
10068  _spoolss_DeletePrinterDataEx
10069 ****************************************************************/
10070
10071 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
10072                                     struct spoolss_DeletePrinterDataEx *r)
10073 {
10074         const char *printer;
10075         int             snum=0;
10076         WERROR          status = WERR_OK;
10077         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10078
10079         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
10080
10081         if (!Printer) {
10082                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
10083                         "Invalid handle (%s:%u:%u).\n",
10084                         OUR_HANDLE(r->in.handle)));
10085                 return WERR_INVALID_HANDLE;
10086         }
10087
10088         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10089                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
10090                         "printer properties change denied by handle\n"));
10091                 return WERR_ACCESS_DENIED;
10092         }
10093
10094         if (!r->in.value_name || !r->in.key_name) {
10095                 return WERR_NOT_ENOUGH_MEMORY;
10096         }
10097
10098         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10099                 return WERR_INVALID_HANDLE;
10100         }
10101         printer = lp_const_servicename(snum);
10102
10103         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
10104                                               get_session_info_system(),
10105                                               p->msg_ctx,
10106                                               printer,
10107                                               r->in.key_name,
10108                                               r->in.value_name);
10109         if (W_ERROR_IS_OK(status)) {
10110                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
10111                                                         get_session_info_system(),
10112                                                         p->msg_ctx,
10113                                                         printer);
10114         }
10115
10116         return status;
10117 }
10118
10119 /****************************************************************
10120  _spoolss_EnumPrinterKey
10121 ****************************************************************/
10122
10123 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
10124                                struct spoolss_EnumPrinterKey *r)
10125 {
10126         uint32_t        num_keys;
10127         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10128         int             snum = 0;
10129         WERROR          result = WERR_FILE_NOT_FOUND;
10130         const char **array = NULL;
10131         DATA_BLOB blob;
10132
10133         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
10134
10135         if (!Printer) {
10136                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
10137                         OUR_HANDLE(r->in.handle)));
10138                 return WERR_INVALID_HANDLE;
10139         }
10140
10141         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10142                 return WERR_INVALID_HANDLE;
10143         }
10144
10145         result = winreg_enum_printer_key_internal(p->mem_ctx,
10146                                          get_session_info_system(),
10147                                          p->msg_ctx,
10148                                          lp_const_servicename(snum),
10149                                          r->in.key_name,
10150                                          &num_keys,
10151                                          &array);
10152         if (!W_ERROR_IS_OK(result)) {
10153                 goto done;
10154         }
10155
10156         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
10157                 result = WERR_NOT_ENOUGH_MEMORY;
10158                 goto done;
10159         }
10160
10161         *r->out._ndr_size = r->in.offered / 2;
10162         *r->out.needed = blob.length;
10163
10164         if (r->in.offered < *r->out.needed) {
10165                 result = WERR_MORE_DATA;
10166         } else {
10167                 result = WERR_OK;
10168                 r->out.key_buffer->string_array = array;
10169         }
10170
10171  done:
10172         if (!W_ERROR_IS_OK(result)) {
10173                 TALLOC_FREE(array);
10174                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
10175                         *r->out.needed = 0;
10176                 }
10177         }
10178
10179         return result;
10180 }
10181
10182 /****************************************************************
10183  _spoolss_DeletePrinterKey
10184 ****************************************************************/
10185
10186 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
10187                                  struct spoolss_DeletePrinterKey *r)
10188 {
10189         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10190         int                     snum=0;
10191         WERROR                  status;
10192         const char *printer;
10193         struct dcerpc_binding_handle *b;
10194         TALLOC_CTX *tmp_ctx;
10195
10196         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10197
10198         if (!Printer) {
10199                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10200                         OUR_HANDLE(r->in.handle)));
10201                 return WERR_INVALID_HANDLE;
10202         }
10203
10204         /* if keyname == NULL, return error */
10205         if ( !r->in.key_name )
10206                 return WERR_INVALID_PARAMETER;
10207
10208         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10209                 return WERR_INVALID_HANDLE;
10210         }
10211
10212         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10213                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
10214                         "printer properties change denied by handle\n"));
10215                 return WERR_ACCESS_DENIED;
10216         }
10217
10218         printer = lp_const_servicename(snum);
10219
10220         tmp_ctx = talloc_new(p->mem_ctx);
10221         if (!tmp_ctx) {
10222                 return WERR_NOT_ENOUGH_MEMORY;
10223         }
10224
10225         status = winreg_printer_binding_handle(tmp_ctx,
10226                                                get_session_info_system(),
10227                                                p->msg_ctx,
10228                                                &b);
10229         if (!W_ERROR_IS_OK(status)) {
10230                 goto done;
10231         }
10232
10233         /* delete the key and all subkeys */
10234         status = winreg_delete_printer_key(tmp_ctx, b,
10235                                            printer,
10236                                            r->in.key_name);
10237         if (W_ERROR_IS_OK(status)) {
10238                 status = winreg_printer_update_changeid(tmp_ctx, b,
10239                                                         printer);
10240         }
10241
10242 done:
10243         talloc_free(tmp_ctx);
10244         return status;
10245 }
10246
10247 /****************************************************************
10248  _spoolss_EnumPrinterDataEx
10249 ****************************************************************/
10250
10251 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10252                                   struct spoolss_EnumPrinterDataEx *r)
10253 {
10254         uint32_t        count = 0;
10255         struct spoolss_PrinterEnumValues *info = NULL;
10256         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10257         int             snum;
10258         WERROR          result;
10259
10260         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10261
10262         *r->out.count = 0;
10263         *r->out.needed = 0;
10264         *r->out.info = NULL;
10265
10266         if (!Printer) {
10267                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10268                         OUR_HANDLE(r->in.handle)));
10269                 return WERR_INVALID_HANDLE;
10270         }
10271
10272         /*
10273          * first check for a keyname of NULL or "".  Win2k seems to send
10274          * this a lot and we should send back WERR_INVALID_PARAMETER
10275          * no need to spend time looking up the printer in this case.
10276          * --jerry
10277          */
10278
10279         if (!strlen(r->in.key_name)) {
10280                 result = WERR_INVALID_PARAMETER;
10281                 goto done;
10282         }
10283
10284         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10285                 return WERR_INVALID_HANDLE;
10286         }
10287
10288         /* now look for a match on the key name */
10289         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10290                                             get_session_info_system(),
10291                                             p->msg_ctx,
10292                                             lp_const_servicename(snum),
10293                                             r->in.key_name,
10294                                             &count,
10295                                             &info);
10296         if (!W_ERROR_IS_OK(result)) {
10297                 goto done;
10298         }
10299
10300 #if 0 /* FIXME - gd */
10301         /* housekeeping information in the reply */
10302
10303         /* Fix from Martin Zielinski <mz@seh.de> - ensure
10304          * the hand marshalled container size is a multiple
10305          * of 4 bytes for RPC alignment.
10306          */
10307
10308         if (needed % 4) {
10309                 needed += 4-(needed % 4);
10310         }
10311 #endif
10312         *r->out.count   = count;
10313         *r->out.info    = info;
10314
10315  done:
10316         if (!W_ERROR_IS_OK(result)) {
10317                 return result;
10318         }
10319
10320         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10321                                                spoolss_EnumPrinterDataEx,
10322                                                *r->out.info,
10323                                                *r->out.count);
10324         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10325         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10326
10327         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10328 }
10329
10330 /****************************************************************************
10331 ****************************************************************************/
10332
10333 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10334                                                  const char *servername,
10335                                                  const char *environment,
10336                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
10337 {
10338         WERROR werr;
10339         char *path = NULL;
10340
10341         werr = compose_spoolss_server_path(mem_ctx,
10342                                            servername,
10343                                            environment,
10344                                            SPOOLSS_PRTPROCS_PATH,
10345                                            &path);
10346         if (!W_ERROR_IS_OK(werr)) {
10347                 return werr;
10348         }
10349
10350         DEBUG(4,("print processor directory: [%s]\n", path));
10351
10352         r->directory_name = path;
10353
10354         return WERR_OK;
10355 }
10356
10357 /****************************************************************
10358  _spoolss_GetPrintProcessorDirectory
10359 ****************************************************************/
10360
10361 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10362                                            struct spoolss_GetPrintProcessorDirectory *r)
10363 {
10364         WERROR result;
10365         char *prnproc_share = NULL;
10366         bool prnproc_share_exists = false;
10367         int snum;
10368
10369         /* that's an [in out] buffer */
10370
10371         if (!r->in.buffer && (r->in.offered != 0)) {
10372                 result = WERR_INVALID_PARAMETER;
10373                 goto err_info_free;
10374         }
10375
10376         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10377                 r->in.level));
10378
10379         *r->out.needed = 0;
10380
10381         /* r->in.level is ignored */
10382
10383         /* We always should reply with a local print processor directory so that
10384          * users are not forced to have a [prnproc$] share on the Samba spoolss
10385          * server, if users decide to do so, lets announce it though - Guenther */
10386
10387         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10388         if (!prnproc_share) {
10389                 result = WERR_NOT_ENOUGH_MEMORY;
10390                 goto err_info_free;
10391         }
10392         if (snum != -1) {
10393                 prnproc_share_exists = true;
10394         }
10395
10396         result = getprintprocessordirectory_level_1(p->mem_ctx,
10397                                                     prnproc_share_exists ? r->in.server : NULL,
10398                                                     r->in.environment,
10399                                                     &r->out.info->info1);
10400         if (!W_ERROR_IS_OK(result)) {
10401                 goto err_info_free;
10402         }
10403
10404         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10405                                                                                    r->out.info, r->in.level);
10406         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10407
10408         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10409
10410 err_info_free:
10411         TALLOC_FREE(r->out.info);
10412         return result;
10413 }
10414
10415 /*******************************************************************
10416  ********************************************************************/
10417
10418 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10419                                const char *dllname)
10420 {
10421         enum ndr_err_code ndr_err;
10422         struct spoolss_MonitorUi ui;
10423
10424         ui.dll_name = dllname;
10425
10426         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10427                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10428         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10429                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10430         }
10431         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10432 }
10433
10434 /*******************************************************************
10435  Streams the monitor UI DLL name in UNICODE
10436 *******************************************************************/
10437
10438 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10439                                struct security_token *token, DATA_BLOB *in,
10440                                DATA_BLOB *out, uint32_t *needed)
10441 {
10442         const char *dllname = "tcpmonui.dll";
10443
10444         *needed = (strlen(dllname)+1) * 2;
10445
10446         if (out->length < *needed) {
10447                 return WERR_INSUFFICIENT_BUFFER;
10448         }
10449
10450         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10451                 return WERR_NOT_ENOUGH_MEMORY;
10452         }
10453
10454         return WERR_OK;
10455 }
10456
10457 /*******************************************************************
10458  ********************************************************************/
10459
10460 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10461                              struct spoolss_PortData1 *port1,
10462                              const DATA_BLOB *buf)
10463 {
10464         enum ndr_err_code ndr_err;
10465         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10466                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10467         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10468                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10469         }
10470         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10471 }
10472
10473 /*******************************************************************
10474  ********************************************************************/
10475
10476 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10477                              struct spoolss_PortData2 *port2,
10478                              const DATA_BLOB *buf)
10479 {
10480         enum ndr_err_code ndr_err;
10481         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10482                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10483         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10484                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10485         }
10486         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10487 }
10488
10489 /*******************************************************************
10490  Create a new TCP/IP port
10491 *******************************************************************/
10492
10493 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10494                              struct security_token *token, DATA_BLOB *in,
10495                              DATA_BLOB *out, uint32_t *needed)
10496 {
10497         struct spoolss_PortData1 port1;
10498         struct spoolss_PortData2 port2;
10499         char *device_uri = NULL;
10500         uint32_t version;
10501
10502         const char *portname;
10503         const char *hostaddress;
10504         const char *queue;
10505         uint32_t port_number;
10506         uint32_t protocol;
10507
10508         /* peek for spoolss_PortData version */
10509
10510         if (!in || (in->length < (128 + 4))) {
10511                 return WERR_GEN_FAILURE;
10512         }
10513
10514         version = IVAL(in->data, 128);
10515
10516         switch (version) {
10517                 case 1:
10518                         ZERO_STRUCT(port1);
10519
10520                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10521                                 return WERR_NOT_ENOUGH_MEMORY;
10522                         }
10523
10524                         portname        = port1.portname;
10525                         hostaddress     = port1.hostaddress;
10526                         queue           = port1.queue;
10527                         protocol        = port1.protocol;
10528                         port_number     = port1.port_number;
10529
10530                         break;
10531                 case 2:
10532                         ZERO_STRUCT(port2);
10533
10534                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10535                                 return WERR_NOT_ENOUGH_MEMORY;
10536                         }
10537
10538                         portname        = port2.portname;
10539                         hostaddress     = port2.hostaddress;
10540                         queue           = port2.queue;
10541                         protocol        = port2.protocol;
10542                         port_number     = port2.port_number;
10543
10544                         break;
10545                 default:
10546                         DEBUG(1,("xcvtcp_addport: "
10547                                 "unknown version of port_data: %d\n", version));
10548                         return WERR_UNKNOWN_PORT;
10549         }
10550
10551         /* create the device URI and call the add_port_hook() */
10552
10553         switch (protocol) {
10554         case PROTOCOL_RAWTCP_TYPE:
10555                 device_uri = talloc_asprintf(mem_ctx,
10556                                 "socket://%s:%d/", hostaddress,
10557                                 port_number);
10558                 break;
10559
10560         case PROTOCOL_LPR_TYPE:
10561                 device_uri = talloc_asprintf(mem_ctx,
10562                         "lpr://%s/%s", hostaddress, queue );
10563                 break;
10564
10565         default:
10566                 return WERR_UNKNOWN_PORT;
10567         }
10568
10569         if (!device_uri) {
10570                 return WERR_NOT_ENOUGH_MEMORY;
10571         }
10572
10573         return add_port_hook(mem_ctx, token, portname, device_uri);
10574 }
10575
10576 /*******************************************************************
10577 *******************************************************************/
10578
10579 struct xcv_api_table xcvtcp_cmds[] = {
10580         { "MonitorUI",  xcvtcp_monitorui },
10581         { "AddPort",    xcvtcp_addport},
10582         { NULL,         NULL }
10583 };
10584
10585 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10586                                      struct security_token *token, const char *command,
10587                                      DATA_BLOB *inbuf,
10588                                      DATA_BLOB *outbuf,
10589                                      uint32_t *needed )
10590 {
10591         int i;
10592
10593         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10594
10595         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10596                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10597                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10598         }
10599
10600         return WERR_INVALID_FUNCTION;
10601 }
10602
10603 /*******************************************************************
10604 *******************************************************************/
10605 #if 0   /* don't support management using the "Local Port" monitor */
10606
10607 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10608                                  struct security_token *token, DATA_BLOB *in,
10609                                  DATA_BLOB *out, uint32_t *needed)
10610 {
10611         const char *dllname = "localui.dll";
10612
10613         *needed = (strlen(dllname)+1) * 2;
10614
10615         if (out->length < *needed) {
10616                 return WERR_INSUFFICIENT_BUFFER;
10617         }
10618
10619         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10620                 return WERR_NOT_ENOUGH_MEMORY;
10621         }
10622
10623         return WERR_OK;
10624 }
10625
10626 /*******************************************************************
10627 *******************************************************************/
10628
10629 struct xcv_api_table xcvlocal_cmds[] = {
10630         { "MonitorUI",  xcvlocal_monitorui },
10631         { NULL,         NULL }
10632 };
10633 #else
10634 struct xcv_api_table xcvlocal_cmds[] = {
10635         { NULL,         NULL }
10636 };
10637 #endif
10638
10639
10640
10641 /*******************************************************************
10642 *******************************************************************/
10643
10644 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10645                                        struct security_token *token, const char *command,
10646                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10647                                        uint32_t *needed)
10648 {
10649         int i;
10650
10651         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10652
10653         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10654                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10655                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10656         }
10657         return WERR_INVALID_FUNCTION;
10658 }
10659
10660 /****************************************************************
10661  _spoolss_XcvData
10662 ****************************************************************/
10663
10664 WERROR _spoolss_XcvData(struct pipes_struct *p,
10665                         struct spoolss_XcvData *r)
10666 {
10667         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10668         DATA_BLOB out_data = data_blob_null;
10669         WERROR werror;
10670
10671         if (!Printer) {
10672                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10673                         OUR_HANDLE(r->in.handle)));
10674                 return WERR_INVALID_HANDLE;
10675         }
10676
10677         /* Has to be a handle to the TCP/IP port monitor */
10678
10679         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10680                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10681                 return WERR_INVALID_HANDLE;
10682         }
10683
10684         /* requires administrative access to the server */
10685
10686         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10687                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10688                 return WERR_ACCESS_DENIED;
10689         }
10690
10691         /* Allocate the outgoing buffer */
10692
10693         if (r->in.out_data_size) {
10694                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10695                 if (out_data.data == NULL) {
10696                         return WERR_NOT_ENOUGH_MEMORY;
10697                 }
10698         }
10699
10700         switch ( Printer->printer_type ) {
10701         case SPLHND_PORTMON_TCP:
10702                 werror = process_xcvtcp_command(p->mem_ctx,
10703                                                 p->session_info->security_token,
10704                                                 r->in.function_name,
10705                                                 &r->in.in_data, &out_data,
10706                                                 r->out.needed);
10707                 break;
10708         case SPLHND_PORTMON_LOCAL:
10709                 werror = process_xcvlocal_command(p->mem_ctx,
10710                                                   p->session_info->security_token,
10711                                                   r->in.function_name,
10712                                                   &r->in.in_data, &out_data,
10713                                                   r->out.needed);
10714                 break;
10715         default:
10716                 werror = WERR_INVALID_PRINT_MONITOR;
10717         }
10718
10719         if (!W_ERROR_IS_OK(werror)) {
10720                 return werror;
10721         }
10722
10723         *r->out.status_code = 0;
10724
10725         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10726                 memcpy(r->out.out_data, out_data.data,
10727                         MIN(r->in.out_data_size, out_data.length));
10728         }
10729
10730         return WERR_OK;
10731 }
10732
10733 /****************************************************************
10734  _spoolss_AddPrintProcessor
10735 ****************************************************************/
10736
10737 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10738                                   struct spoolss_AddPrintProcessor *r)
10739 {
10740         /* for now, just indicate success and ignore the add.  We'll
10741            automatically set the winprint processor for printer
10742            entries later.  Used to debug the LexMark Optra S 1855 PCL
10743            driver --jerry */
10744
10745         return WERR_OK;
10746 }
10747
10748 /****************************************************************
10749  _spoolss_AddPort
10750 ****************************************************************/
10751
10752 WERROR _spoolss_AddPort(struct pipes_struct *p,
10753                         struct spoolss_AddPort *r)
10754 {
10755         /* do what w2k3 does */
10756
10757         return WERR_NOT_SUPPORTED;
10758 }
10759
10760 /****************************************************************
10761  _spoolss_GetPrinterDriver
10762 ****************************************************************/
10763
10764 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10765                                  struct spoolss_GetPrinterDriver *r)
10766 {
10767         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10768         return WERR_NOT_SUPPORTED;
10769 }
10770
10771 /****************************************************************
10772  _spoolss_ReadPrinter
10773 ****************************************************************/
10774
10775 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10776                             struct spoolss_ReadPrinter *r)
10777 {
10778         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10779         return WERR_NOT_SUPPORTED;
10780 }
10781
10782 /****************************************************************
10783  _spoolss_WaitForPrinterChange
10784 ****************************************************************/
10785
10786 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10787                                      struct spoolss_WaitForPrinterChange *r)
10788 {
10789         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10790         return WERR_NOT_SUPPORTED;
10791 }
10792
10793 /****************************************************************
10794  _spoolss_ConfigurePort
10795 ****************************************************************/
10796
10797 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10798                               struct spoolss_ConfigurePort *r)
10799 {
10800         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10801         return WERR_NOT_SUPPORTED;
10802 }
10803
10804 /****************************************************************
10805  _spoolss_DeletePort
10806 ****************************************************************/
10807
10808 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10809                            struct spoolss_DeletePort *r)
10810 {
10811         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10812         return WERR_NOT_SUPPORTED;
10813 }
10814
10815 /****************************************************************
10816  _spoolss_CreatePrinterIC
10817 ****************************************************************/
10818
10819 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10820                                 struct spoolss_CreatePrinterIC *r)
10821 {
10822         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10823         return WERR_NOT_SUPPORTED;
10824 }
10825
10826 /****************************************************************
10827  _spoolss_PlayGDIScriptOnPrinterIC
10828 ****************************************************************/
10829
10830 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10831                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10832 {
10833         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10834         return WERR_NOT_SUPPORTED;
10835 }
10836
10837 /****************************************************************
10838  _spoolss_DeletePrinterIC
10839 ****************************************************************/
10840
10841 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10842                                 struct spoolss_DeletePrinterIC *r)
10843 {
10844         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10845         return WERR_NOT_SUPPORTED;
10846 }
10847
10848 /****************************************************************
10849  _spoolss_AddPrinterConnection
10850 ****************************************************************/
10851
10852 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10853                                      struct spoolss_AddPrinterConnection *r)
10854 {
10855         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10856         return WERR_NOT_SUPPORTED;
10857 }
10858
10859 /****************************************************************
10860  _spoolss_DeletePrinterConnection
10861 ****************************************************************/
10862
10863 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10864                                         struct spoolss_DeletePrinterConnection *r)
10865 {
10866         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10867         return WERR_NOT_SUPPORTED;
10868 }
10869
10870 /****************************************************************
10871  _spoolss_PrinterMessageBox
10872 ****************************************************************/
10873
10874 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10875                                   struct spoolss_PrinterMessageBox *r)
10876 {
10877         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10878         return WERR_NOT_SUPPORTED;
10879 }
10880
10881 /****************************************************************
10882  _spoolss_AddMonitor
10883 ****************************************************************/
10884
10885 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10886                            struct spoolss_AddMonitor *r)
10887 {
10888         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10889         return WERR_NOT_SUPPORTED;
10890 }
10891
10892 /****************************************************************
10893  _spoolss_DeleteMonitor
10894 ****************************************************************/
10895
10896 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10897                               struct spoolss_DeleteMonitor *r)
10898 {
10899         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10900         return WERR_NOT_SUPPORTED;
10901 }
10902
10903 /****************************************************************
10904  _spoolss_DeletePrintProcessor
10905 ****************************************************************/
10906
10907 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10908                                      struct spoolss_DeletePrintProcessor *r)
10909 {
10910         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10911         return WERR_NOT_SUPPORTED;
10912 }
10913
10914 /****************************************************************
10915  _spoolss_AddPrintProvidor
10916 ****************************************************************/
10917
10918 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10919                                  struct spoolss_AddPrintProvidor *r)
10920 {
10921         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10922         return WERR_NOT_SUPPORTED;
10923 }
10924
10925 /****************************************************************
10926  _spoolss_DeletePrintProvidor
10927 ****************************************************************/
10928
10929 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10930                                     struct spoolss_DeletePrintProvidor *r)
10931 {
10932         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10933         return WERR_NOT_SUPPORTED;
10934 }
10935
10936 /****************************************************************
10937  _spoolss_FindFirstPrinterChangeNotification
10938 ****************************************************************/
10939
10940 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10941                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10942 {
10943         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10944         return WERR_NOT_SUPPORTED;
10945 }
10946
10947 /****************************************************************
10948  _spoolss_FindNextPrinterChangeNotification
10949 ****************************************************************/
10950
10951 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10952                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10953 {
10954         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10955         return WERR_NOT_SUPPORTED;
10956 }
10957
10958 /****************************************************************
10959  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10960 ****************************************************************/
10961
10962 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10963                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10964 {
10965         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10966         return WERR_NOT_SUPPORTED;
10967 }
10968
10969 /****************************************************************
10970  _spoolss_ReplyOpenPrinter
10971 ****************************************************************/
10972
10973 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10974                                  struct spoolss_ReplyOpenPrinter *r)
10975 {
10976         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10977         return WERR_NOT_SUPPORTED;
10978 }
10979
10980 /****************************************************************
10981  _spoolss_RouterReplyPrinter
10982 ****************************************************************/
10983
10984 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10985                                    struct spoolss_RouterReplyPrinter *r)
10986 {
10987         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10988         return WERR_NOT_SUPPORTED;
10989 }
10990
10991 /****************************************************************
10992  _spoolss_ReplyClosePrinter
10993 ****************************************************************/
10994
10995 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10996                                   struct spoolss_ReplyClosePrinter *r)
10997 {
10998         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10999         return WERR_NOT_SUPPORTED;
11000 }
11001
11002 /****************************************************************
11003  _spoolss_AddPortEx
11004 ****************************************************************/
11005
11006 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
11007                           struct spoolss_AddPortEx *r)
11008 {
11009         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11010         return WERR_NOT_SUPPORTED;
11011 }
11012
11013 /****************************************************************
11014  _spoolss_RouterFindFirstPrinterChangeNotification
11015 ****************************************************************/
11016
11017 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
11018                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
11019 {
11020         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11021         return WERR_NOT_SUPPORTED;
11022 }
11023
11024 /****************************************************************
11025  _spoolss_SpoolerInit
11026 ****************************************************************/
11027
11028 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
11029                             struct spoolss_SpoolerInit *r)
11030 {
11031         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11032         return WERR_NOT_SUPPORTED;
11033 }
11034
11035 /****************************************************************
11036  _spoolss_ResetPrinterEx
11037 ****************************************************************/
11038
11039 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
11040                                struct spoolss_ResetPrinterEx *r)
11041 {
11042         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11043         return WERR_NOT_SUPPORTED;
11044 }
11045
11046 /****************************************************************
11047  _spoolss_RouterReplyPrinterEx
11048 ****************************************************************/
11049
11050 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
11051                                      struct spoolss_RouterReplyPrinterEx *r)
11052 {
11053         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11054         return WERR_NOT_SUPPORTED;
11055 }
11056
11057 /****************************************************************
11058  _spoolss_44
11059 ****************************************************************/
11060
11061 WERROR _spoolss_44(struct pipes_struct *p,
11062                    struct spoolss_44 *r)
11063 {
11064         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11065         return WERR_NOT_SUPPORTED;
11066 }
11067
11068 /****************************************************************
11069  _spoolss_SetPort
11070 ****************************************************************/
11071
11072 WERROR _spoolss_SetPort(struct pipes_struct *p,
11073                         struct spoolss_SetPort *r)
11074 {
11075         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11076         return WERR_NOT_SUPPORTED;
11077 }
11078
11079 /****************************************************************
11080  _spoolss_4a
11081 ****************************************************************/
11082
11083 WERROR _spoolss_4a(struct pipes_struct *p,
11084                    struct spoolss_4a *r)
11085 {
11086         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11087         return WERR_NOT_SUPPORTED;
11088 }
11089
11090 /****************************************************************
11091  _spoolss_4b
11092 ****************************************************************/
11093
11094 WERROR _spoolss_4b(struct pipes_struct *p,
11095                    struct spoolss_4b *r)
11096 {
11097         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11098         return WERR_NOT_SUPPORTED;
11099 }
11100
11101 /****************************************************************
11102  _spoolss_4c
11103 ****************************************************************/
11104
11105 WERROR _spoolss_4c(struct pipes_struct *p,
11106                    struct spoolss_4c *r)
11107 {
11108         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11109         return WERR_NOT_SUPPORTED;
11110 }
11111
11112 /****************************************************************
11113  _spoolss_53
11114 ****************************************************************/
11115
11116 WERROR _spoolss_53(struct pipes_struct *p,
11117                    struct spoolss_53 *r)
11118 {
11119         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11120         return WERR_NOT_SUPPORTED;
11121 }
11122
11123 /****************************************************************
11124  _spoolss_AddPerMachineConnection
11125 ****************************************************************/
11126
11127 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
11128                                         struct spoolss_AddPerMachineConnection *r)
11129 {
11130         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11131         return WERR_NOT_SUPPORTED;
11132 }
11133
11134 /****************************************************************
11135  _spoolss_DeletePerMachineConnection
11136 ****************************************************************/
11137
11138 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
11139                                            struct spoolss_DeletePerMachineConnection *r)
11140 {
11141         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11142         return WERR_NOT_SUPPORTED;
11143 }
11144
11145 /****************************************************************
11146  _spoolss_EnumPerMachineConnections
11147 ****************************************************************/
11148
11149 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
11150                                           struct spoolss_EnumPerMachineConnections *r)
11151 {
11152         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11153         return WERR_NOT_SUPPORTED;
11154 }
11155
11156 /****************************************************************
11157  _spoolss_5a
11158 ****************************************************************/
11159
11160 WERROR _spoolss_5a(struct pipes_struct *p,
11161                    struct spoolss_5a *r)
11162 {
11163         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11164         return WERR_NOT_SUPPORTED;
11165 }
11166
11167 /****************************************************************
11168  _spoolss_5b
11169 ****************************************************************/
11170
11171 WERROR _spoolss_5b(struct pipes_struct *p,
11172                    struct spoolss_5b *r)
11173 {
11174         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11175         return WERR_NOT_SUPPORTED;
11176 }
11177
11178 /****************************************************************
11179  _spoolss_5c
11180 ****************************************************************/
11181
11182 WERROR _spoolss_5c(struct pipes_struct *p,
11183                    struct spoolss_5c *r)
11184 {
11185         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11186         return WERR_NOT_SUPPORTED;
11187 }
11188
11189 /****************************************************************
11190  _spoolss_5d
11191 ****************************************************************/
11192
11193 WERROR _spoolss_5d(struct pipes_struct *p,
11194                    struct spoolss_5d *r)
11195 {
11196         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11197         return WERR_NOT_SUPPORTED;
11198 }
11199
11200 /****************************************************************
11201  _spoolss_5e
11202 ****************************************************************/
11203
11204 WERROR _spoolss_5e(struct pipes_struct *p,
11205                    struct spoolss_5e *r)
11206 {
11207         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11208         return WERR_NOT_SUPPORTED;
11209 }
11210
11211 /****************************************************************
11212  _spoolss_5f
11213 ****************************************************************/
11214
11215 WERROR _spoolss_5f(struct pipes_struct *p,
11216                    struct spoolss_5f *r)
11217 {
11218         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11219         return WERR_NOT_SUPPORTED;
11220 }
11221
11222 /****************************************************************
11223  _spoolss_60
11224 ****************************************************************/
11225
11226 WERROR _spoolss_60(struct pipes_struct *p,
11227                    struct spoolss_60 *r)
11228 {
11229         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11230         return WERR_NOT_SUPPORTED;
11231 }
11232
11233 /****************************************************************
11234  _spoolss_SendRecvBidiData
11235 ****************************************************************/
11236
11237 WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
11238                                  struct spoolss_SendRecvBidiData *r)
11239 {
11240         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11241         return WERR_NOT_SUPPORTED;
11242 }
11243
11244 /****************************************************************
11245  _spoolss_62
11246 ****************************************************************/
11247
11248 WERROR _spoolss_62(struct pipes_struct *p,
11249                    struct spoolss_62 *r)
11250 {
11251         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11252         return WERR_NOT_SUPPORTED;
11253 }
11254
11255 /****************************************************************
11256  _spoolss_63
11257 ****************************************************************/
11258
11259 WERROR _spoolss_63(struct pipes_struct *p,
11260                    struct spoolss_63 *r)
11261 {
11262         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11263         return WERR_NOT_SUPPORTED;
11264 }
11265
11266 /****************************************************************
11267  _spoolss_64
11268 ****************************************************************/
11269
11270 WERROR _spoolss_64(struct pipes_struct *p,
11271                    struct spoolss_64 *r)
11272 {
11273         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11274         return WERR_NOT_SUPPORTED;
11275 }
11276
11277 /****************************************************************
11278  _spoolss_65
11279 ****************************************************************/
11280
11281 WERROR _spoolss_65(struct pipes_struct *p,
11282                    struct spoolss_65 *r)
11283 {
11284         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11285         return WERR_NOT_SUPPORTED;
11286 }
11287
11288 /****************************************************************
11289  _spoolss_GetCorePrinterDrivers
11290 ****************************************************************/
11291
11292 HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11293                                        struct spoolss_GetCorePrinterDrivers *r)
11294 {
11295         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11296         return HRES_ERROR_NOT_SUPPORTED;
11297 }
11298
11299 /****************************************************************
11300  _spoolss_67
11301 ****************************************************************/
11302
11303 WERROR _spoolss_67(struct pipes_struct *p,
11304                    struct spoolss_67 *r)
11305 {
11306         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11307         return WERR_NOT_SUPPORTED;
11308 }
11309
11310 /****************************************************************
11311  _spoolss_GetPrinterDriverPackagePath
11312 ****************************************************************/
11313
11314 HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11315                                              struct spoolss_GetPrinterDriverPackagePath *r)
11316 {
11317         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11318         return HRES_ERROR_NOT_SUPPORTED;
11319 }
11320
11321 /****************************************************************
11322  _spoolss_69
11323 ****************************************************************/
11324
11325 WERROR _spoolss_69(struct pipes_struct *p,
11326                    struct spoolss_69 *r)
11327 {
11328         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11329         return WERR_NOT_SUPPORTED;
11330 }
11331
11332 /****************************************************************
11333  _spoolss_6a
11334 ****************************************************************/
11335
11336 WERROR _spoolss_6a(struct pipes_struct *p,
11337                    struct spoolss_6a *r)
11338 {
11339         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11340         return WERR_NOT_SUPPORTED;
11341 }
11342
11343 /****************************************************************
11344  _spoolss_6b
11345 ****************************************************************/
11346
11347 WERROR _spoolss_6b(struct pipes_struct *p,
11348                    struct spoolss_6b *r)
11349 {
11350         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11351         return WERR_NOT_SUPPORTED;
11352 }
11353
11354 /****************************************************************
11355  _spoolss_6c
11356 ****************************************************************/
11357
11358 WERROR _spoolss_6c(struct pipes_struct *p,
11359                    struct spoolss_6c *r)
11360 {
11361         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11362         return WERR_NOT_SUPPORTED;
11363 }
11364
11365 /****************************************************************
11366  _spoolss_6d
11367 ****************************************************************/
11368
11369 WERROR _spoolss_6d(struct pipes_struct *p,
11370                    struct spoolss_6d *r)
11371 {
11372         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11373         return WERR_NOT_SUPPORTED;
11374 }
11375
11376 /****************************************************************
11377  _spoolss_GetJobNamedPropertyValue
11378 ****************************************************************/
11379
11380 WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
11381                                          struct spoolss_GetJobNamedPropertyValue *r)
11382 {
11383         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11384         return WERR_NOT_SUPPORTED;
11385 }
11386
11387 /****************************************************************
11388  _spoolss_SetJobNamedProperty
11389 ****************************************************************/
11390
11391 WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
11392                                     struct spoolss_SetJobNamedProperty *r)
11393 {
11394         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11395         return WERR_NOT_SUPPORTED;
11396 }
11397
11398 /****************************************************************
11399  _spoolss_DeleteJobNamedProperty
11400 ****************************************************************/
11401
11402 WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
11403                                        struct spoolss_DeleteJobNamedProperty *r)
11404 {
11405         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11406         return WERR_NOT_SUPPORTED;
11407 }
11408
11409 /****************************************************************
11410  _spoolss_EnumJobNamedProperties
11411 ****************************************************************/
11412
11413 WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
11414                                        struct spoolss_EnumJobNamedProperties *r)
11415 {
11416         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11417         return WERR_NOT_SUPPORTED;
11418 }
11419
11420 /****************************************************************
11421  _spoolss_72
11422 ****************************************************************/
11423
11424 WERROR _spoolss_72(struct pipes_struct *p,
11425                    struct spoolss_72 *r)
11426 {
11427         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11428         return WERR_NOT_SUPPORTED;
11429 }
11430
11431 /****************************************************************
11432  _spoolss_73
11433 ****************************************************************/
11434
11435 WERROR _spoolss_73(struct pipes_struct *p,
11436                    struct spoolss_73 *r)
11437 {
11438         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11439         return WERR_NOT_SUPPORTED;
11440 }
11441
11442 /****************************************************************
11443  _spoolss_RpcLogJobInfoForBranchOffice
11444 ****************************************************************/
11445
11446 WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
11447                                           struct spoolss_LogJobInfoForBranchOffice *r)
11448 {
11449         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11450         return WERR_NOT_SUPPORTED;
11451 }