lib: Use messaging_send_all instead of message_send_all
[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                 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
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         /*
4181          * These two are not used by NT+ according to MSDN. However the values
4182          * we saw on Windows Server 2012 and 2016 are always set to the 0xafc8.
4183          */
4184         r->device_not_selected_timeout          = 0xafc8; /* 45 sec */
4185         r->transmission_retry_timeout           = 0xafc8; /* 45 sec */
4186
4187         return WERR_OK;
4188 }
4189
4190 /********************************************************************
4191  * construct_printer_info_6
4192  * fill a spoolss_PrinterInfo6 struct
4193  ********************************************************************/
4194
4195 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4196                                       struct messaging_context *msg_ctx,
4197                                       const struct spoolss_PrinterInfo2 *info2,
4198                                       const char *servername,
4199                                       struct spoolss_PrinterInfo6 *r,
4200                                       int snum)
4201 {
4202         print_status_struct status;
4203
4204         print_queue_length(msg_ctx, snum, &status);
4205
4206         r->status = nt_printq_status(status.status);
4207
4208         return WERR_OK;
4209 }
4210
4211 /********************************************************************
4212  * construct_printer_info7
4213  * fill a spoolss_PrinterInfo7 struct
4214  ********************************************************************/
4215
4216 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4217                                       struct messaging_context *msg_ctx,
4218                                       const char *servername,
4219                                       struct spoolss_PrinterInfo7 *r,
4220                                       int snum)
4221 {
4222         const struct auth_session_info *session_info;
4223         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4224         char *printer;
4225         WERROR werr;
4226         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4227         if (tmp_ctx == NULL) {
4228                 return WERR_NOT_ENOUGH_MEMORY;
4229         }
4230
4231         session_info = get_session_info_system();
4232         SMB_ASSERT(session_info != NULL);
4233
4234         printer = lp_servicename(tmp_ctx, snum);
4235         if (printer == NULL) {
4236                 DEBUG(0, ("invalid printer snum %d\n", snum));
4237                 werr = WERR_INVALID_PARAMETER;
4238                 goto out_tmp_free;
4239         }
4240
4241         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4242                                  servername, printer, &pinfo2)) {
4243                 struct GUID guid;
4244                 char *guidstr;
4245                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4246                                            printer, &guid);
4247                 if (!W_ERROR_IS_OK(werr)) {
4248                         /*
4249                          * If we do not have a GUID entry in the registry, then
4250                          * try to retrieve it from AD and store it now.
4251                          */
4252                         werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4253                                                         &guid);
4254                         if (!W_ERROR_IS_OK(werr)) {
4255                                 DBG_NOTICE("Failed to retrieve GUID for "
4256                                            "printer [%s] from AD - %s\n",
4257                                            printer,
4258                                            win_errstr(werr));
4259                                 if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
4260                                         /*
4261                                          * If we did not find it in AD, then it
4262                                          * is unpublished and we should reflect
4263                                          * this in the registry and return
4264                                          * success.
4265                                          */
4266                                         DBG_WARNING("Unpublish printer [%s]\n",
4267                                                     pinfo2->sharename);
4268                                         nt_printer_publish(tmp_ctx,
4269                                                            session_info,
4270                                                            msg_ctx,
4271                                                            pinfo2,
4272                                                            DSPRINT_UNPUBLISH);
4273                                         r->guid = talloc_strdup(mem_ctx, "");
4274                                         r->action = DSPRINT_UNPUBLISH;
4275
4276                                         if (r->guid == NULL) {
4277                                                 werr = WERR_NOT_ENOUGH_MEMORY;
4278                                         } else {
4279                                                 werr = WERR_OK;
4280                                         }
4281                                 }
4282                                 goto out_tmp_free;
4283                         }
4284
4285                         werr = nt_printer_guid_store(msg_ctx, printer, guid);
4286                         if (!W_ERROR_IS_OK(werr)) {
4287                                 DEBUG(3, ("failed to store printer %s guid\n",
4288                                           printer));
4289                         }
4290                 }
4291
4292                 /* [MS-RPRN] section 2.2: must use curly-braced GUIDs */
4293                 guidstr = GUID_string2(mem_ctx, &guid);
4294                 if (guidstr == NULL) {
4295                         werr = WERR_NOT_ENOUGH_MEMORY;
4296                         goto out_tmp_free;
4297                 }
4298                 /* Convert GUID string to uppercase otherwise printers
4299                  * are pruned */
4300                 r->guid = talloc_strdup_upper(mem_ctx, guidstr);
4301                 r->action = DSPRINT_PUBLISH;
4302
4303                 TALLOC_FREE(guidstr);
4304         } else {
4305                 r->guid = talloc_strdup(mem_ctx, "");
4306                 r->action = DSPRINT_UNPUBLISH;
4307         }
4308         if (r->guid == NULL) {
4309                 werr = WERR_NOT_ENOUGH_MEMORY;
4310                 goto out_tmp_free;
4311         }
4312
4313         werr = WERR_OK;
4314 out_tmp_free:
4315         talloc_free(tmp_ctx);
4316         return werr;
4317 }
4318
4319 /********************************************************************
4320  * construct_printer_info8
4321  * fill a spoolss_PrinterInfo8 struct
4322  ********************************************************************/
4323
4324 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4325                                       const struct spoolss_PrinterInfo2 *info2,
4326                                       const char *servername,
4327                                       struct spoolss_DeviceModeInfo *r,
4328                                       int snum)
4329 {
4330         WERROR result;
4331         const char *printername;
4332
4333         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4334         if (!W_ERROR_IS_OK(result)) {
4335                 return result;
4336         }
4337
4338         if (info2->devmode != NULL) {
4339                 result = copy_devicemode(mem_ctx,
4340                                          info2->devmode,
4341                                          &r->devmode);
4342                 if (!W_ERROR_IS_OK(result)) {
4343                         return result;
4344                 }
4345         } else if (lp_default_devmode(snum)) {
4346                 result = spoolss_create_default_devmode(mem_ctx,
4347                                                         info2->printername,
4348                                                         &r->devmode);
4349                 if (!W_ERROR_IS_OK(result)) {
4350                         return result;
4351                 }
4352         } else {
4353                 r->devmode = NULL;
4354                 DEBUG(8,("Returning NULL Devicemode!\n"));
4355         }
4356
4357         compose_devicemode_devicename(r->devmode, printername);
4358
4359         return WERR_OK;
4360 }
4361
4362 /********************************************************************
4363  Spoolss_enumprinters.
4364 ********************************************************************/
4365
4366 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4367                                            const struct auth_session_info *session_info,
4368                                            struct messaging_context *msg_ctx,
4369                                            const char *servername,
4370                                            uint32_t level,
4371                                            uint32_t flags,
4372                                            union spoolss_PrinterInfo **info_p,
4373                                            uint32_t *count_p)
4374 {
4375         int snum;
4376         int n_services;
4377         union spoolss_PrinterInfo *info = NULL;
4378         uint32_t count = 0;
4379         WERROR result = WERR_OK;
4380         struct dcerpc_binding_handle *b = NULL;
4381         TALLOC_CTX *tmp_ctx = NULL;
4382
4383         tmp_ctx = talloc_new(mem_ctx);
4384         if (!tmp_ctx) {
4385                 return WERR_NOT_ENOUGH_MEMORY;
4386         }
4387
4388         /*
4389          * printer shares are updated on client enumeration. The background
4390          * printer process updates printer_list.tdb at regular intervals.
4391          */
4392         become_root();
4393         delete_and_reload_printers(server_event_context(), msg_ctx);
4394         unbecome_root();
4395
4396         n_services = lp_numservices();
4397         *count_p = 0;
4398         *info_p = NULL;
4399
4400         for (snum = 0; snum < n_services; snum++) {
4401
4402                 const char *printer;
4403                 struct spoolss_PrinterInfo2 *info2;
4404
4405                 if (!snum_is_shared_printer(snum)) {
4406                         continue;
4407                 }
4408
4409                 printer = lp_const_servicename(snum);
4410
4411                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4412                         printer, snum));
4413
4414                 if (b == NULL) {
4415                         result = winreg_printer_binding_handle(tmp_ctx,
4416                                                                session_info,
4417                                                                msg_ctx,
4418                                                                &b);
4419                         if (!W_ERROR_IS_OK(result)) {
4420                                 goto out;
4421                         }
4422                 }
4423
4424                 result = winreg_create_printer(tmp_ctx, b,
4425                                                printer);
4426                 if (!W_ERROR_IS_OK(result)) {
4427                         goto out;
4428                 }
4429
4430                 info = talloc_realloc(tmp_ctx, info,
4431                                             union spoolss_PrinterInfo,
4432                                             count + 1);
4433                 if (!info) {
4434                         result = WERR_NOT_ENOUGH_MEMORY;
4435                         goto out;
4436                 }
4437
4438                 result = winreg_get_printer(tmp_ctx, b,
4439                                             printer, &info2);
4440                 if (!W_ERROR_IS_OK(result)) {
4441                         goto out;
4442                 }
4443
4444                 switch (level) {
4445                 case 0:
4446                         result = construct_printer_info0(info, session_info,
4447                                                          msg_ctx, info2,
4448                                                          servername,
4449                                                          &info[count].info0, snum);
4450                         break;
4451                 case 1:
4452                         result = construct_printer_info1(info, info2, flags,
4453                                                          servername,
4454                                                          &info[count].info1, snum);
4455                         break;
4456                 case 2:
4457                         result = construct_printer_info2(info, msg_ctx, info2,
4458                                                          servername,
4459                                                          &info[count].info2, snum);
4460                         break;
4461                 case 4:
4462                         result = construct_printer_info4(info, info2,
4463                                                          servername,
4464                                                          &info[count].info4, snum);
4465                         break;
4466                 case 5:
4467                         result = construct_printer_info5(info, info2,
4468                                                          servername,
4469                                                          &info[count].info5, snum);
4470                         break;
4471
4472                 default:
4473                         result = WERR_INVALID_LEVEL;
4474                         goto out;
4475                 }
4476
4477                 if (!W_ERROR_IS_OK(result)) {
4478                         goto out;
4479                 }
4480
4481                 count++;
4482         }
4483
4484 out:
4485         if (W_ERROR_IS_OK(result)) {
4486                 *info_p = talloc_move(mem_ctx, &info);
4487                 *count_p = count;
4488         }
4489
4490         talloc_free(tmp_ctx);
4491
4492         return result;
4493 }
4494
4495 /********************************************************************
4496  * handle enumeration of printers at level 0
4497  ********************************************************************/
4498
4499 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4500                                   const struct auth_session_info *session_info,
4501                                   struct messaging_context *msg_ctx,
4502                                   uint32_t flags,
4503                                   const char *servername,
4504                                   union spoolss_PrinterInfo **info,
4505                                   uint32_t *count)
4506 {
4507         DEBUG(4,("enum_all_printers_info_0\n"));
4508
4509         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4510                                             servername, 0, flags, info, count);
4511 }
4512
4513
4514 /********************************************************************
4515 ********************************************************************/
4516
4517 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4518                                        const struct auth_session_info *session_info,
4519                                        struct messaging_context *msg_ctx,
4520                                        const char *servername,
4521                                        uint32_t flags,
4522                                        union spoolss_PrinterInfo **info,
4523                                        uint32_t *count)
4524 {
4525         DEBUG(4,("enum_all_printers_info_1\n"));
4526
4527         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4528                                             servername, 1, flags, info, count);
4529 }
4530
4531 /********************************************************************
4532  enum_all_printers_info_1_local.
4533 *********************************************************************/
4534
4535 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4536                                              const struct auth_session_info *session_info,
4537                                              struct messaging_context *msg_ctx,
4538                                              const char *servername,
4539                                              union spoolss_PrinterInfo **info,
4540                                              uint32_t *count)
4541 {
4542         DEBUG(4,("enum_all_printers_info_1_local\n"));
4543
4544         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4545                                         servername, PRINTER_ENUM_ICON8, info, count);
4546 }
4547
4548 /********************************************************************
4549  enum_all_printers_info_1_name.
4550 *********************************************************************/
4551
4552 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4553                                             const struct auth_session_info *session_info,
4554                                             struct messaging_context *msg_ctx,
4555                                             const char *servername,
4556                                             union spoolss_PrinterInfo **info,
4557                                             uint32_t *count)
4558 {
4559         const char *s = servername;
4560
4561         DEBUG(4,("enum_all_printers_info_1_name\n"));
4562
4563         if (servername != NULL &&
4564             (servername[0] == '\\') && (servername[1] == '\\')) {
4565                 s = servername + 2;
4566         }
4567
4568         if (!is_myname_or_ipaddr(s)) {
4569                 return WERR_INVALID_NAME;
4570         }
4571
4572         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4573                                         servername, PRINTER_ENUM_ICON8, info, count);
4574 }
4575
4576 /********************************************************************
4577  enum_all_printers_info_1_network.
4578 *********************************************************************/
4579
4580 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4581                                                const struct auth_session_info *session_info,
4582                                                struct messaging_context *msg_ctx,
4583                                                const char *servername,
4584                                                union spoolss_PrinterInfo **info,
4585                                                uint32_t *count)
4586 {
4587         const char *s = servername;
4588
4589         DEBUG(4,("enum_all_printers_info_1_network\n"));
4590
4591         /* If we respond to a enum_printers level 1 on our name with flags
4592            set to PRINTER_ENUM_REMOTE with a list of printers then these
4593            printers incorrectly appear in the APW browse list.
4594            Specifically the printers for the server appear at the workgroup
4595            level where all the other servers in the domain are
4596            listed. Windows responds to this call with a
4597            WERR_CAN_NOT_COMPLETE so we should do the same. */
4598
4599         if (servername != NULL &&
4600             (servername[0] == '\\') && (servername[1] == '\\')) {
4601                  s = servername + 2;
4602         }
4603
4604         if (is_myname_or_ipaddr(s)) {
4605                  return WERR_CAN_NOT_COMPLETE;
4606         }
4607
4608         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4609                                         servername, PRINTER_ENUM_NAME, info, count);
4610 }
4611
4612 /********************************************************************
4613  * api_spoolss_enumprinters
4614  *
4615  * called from api_spoolss_enumprinters (see this to understand)
4616  ********************************************************************/
4617
4618 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4619                                        const struct auth_session_info *session_info,
4620                                        struct messaging_context *msg_ctx,
4621                                        const char *servername,
4622                                        union spoolss_PrinterInfo **info,
4623                                        uint32_t *count)
4624 {
4625         DEBUG(4,("enum_all_printers_info_2\n"));
4626
4627         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4628                                             servername, 2, 0, info, count);
4629 }
4630
4631 /********************************************************************
4632  * handle enumeration of printers at level 1
4633  ********************************************************************/
4634
4635 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4636                                   const struct auth_session_info *session_info,
4637                                   struct messaging_context *msg_ctx,
4638                                   uint32_t flags,
4639                                   const char *servername,
4640                                   union spoolss_PrinterInfo **info,
4641                                   uint32_t *count)
4642 {
4643         /* Not all the flags are equals */
4644
4645         if (flags & PRINTER_ENUM_LOCAL) {
4646                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4647                                                       msg_ctx, servername, info, count);
4648         }
4649
4650         if (flags & PRINTER_ENUM_NAME) {
4651                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4652                                                      msg_ctx, servername, info,
4653                                                      count);
4654         }
4655
4656         if (flags & PRINTER_ENUM_NETWORK) {
4657                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4658                                                         msg_ctx, servername, info,
4659                                                         count);
4660         }
4661
4662         return WERR_OK; /* NT4sp5 does that */
4663 }
4664
4665 /********************************************************************
4666  * handle enumeration of printers at level 2
4667  ********************************************************************/
4668
4669 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4670                                   const struct auth_session_info *session_info,
4671                                   struct messaging_context *msg_ctx,
4672                                   uint32_t flags,
4673                                   const char *servername,
4674                                   union spoolss_PrinterInfo **info,
4675                                   uint32_t *count)
4676 {
4677         if (flags & PRINTER_ENUM_LOCAL) {
4678
4679                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4680                                                 servername,
4681                                                 info, count);
4682         }
4683
4684         if (flags & PRINTER_ENUM_NAME) {
4685                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4686                         return WERR_INVALID_NAME;
4687                 }
4688
4689                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4690                                                 servername,
4691                                                 info, count);
4692         }
4693
4694         if (flags & PRINTER_ENUM_REMOTE) {
4695                 return WERR_INVALID_LEVEL;
4696         }
4697
4698         return WERR_OK;
4699 }
4700
4701 /********************************************************************
4702  * handle enumeration of printers at level 4
4703  ********************************************************************/
4704
4705 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4706                                   const struct auth_session_info *session_info,
4707                                   struct messaging_context *msg_ctx,
4708                                   uint32_t flags,
4709                                   const char *servername,
4710                                   union spoolss_PrinterInfo **info,
4711                                   uint32_t *count)
4712 {
4713         DEBUG(4,("enum_all_printers_info_4\n"));
4714
4715         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4716                                             servername, 4, flags, info, count);
4717 }
4718
4719
4720 /********************************************************************
4721  * handle enumeration of printers at level 5
4722  ********************************************************************/
4723
4724 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4725                                   const struct auth_session_info *session_info,
4726                                   struct messaging_context *msg_ctx,
4727                                   uint32_t flags,
4728                                   const char *servername,
4729                                   union spoolss_PrinterInfo **info,
4730                                   uint32_t *count)
4731 {
4732         DEBUG(4,("enum_all_printers_info_5\n"));
4733
4734         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4735                                             servername, 5, flags, info, count);
4736 }
4737
4738 /****************************************************************
4739  _spoolss_EnumPrinters
4740 ****************************************************************/
4741
4742 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4743                              struct spoolss_EnumPrinters *r)
4744 {
4745         const struct auth_session_info *session_info = get_session_info_system();
4746         WERROR result;
4747
4748         /* that's an [in out] buffer */
4749
4750         if (!r->in.buffer && (r->in.offered != 0)) {
4751                 return WERR_INVALID_PARAMETER;
4752         }
4753
4754         DEBUG(4,("_spoolss_EnumPrinters\n"));
4755
4756         *r->out.needed = 0;
4757         *r->out.count = 0;
4758         *r->out.info = NULL;
4759
4760         /*
4761          * Level 1:
4762          *          flags==PRINTER_ENUM_NAME
4763          *           if name=="" then enumerates all printers
4764          *           if name!="" then enumerate the printer
4765          *          flags==PRINTER_ENUM_REMOTE
4766          *          name is NULL, enumerate printers
4767          * Level 2: name!="" enumerates printers, name can't be NULL
4768          * Level 3: doesn't exist
4769          * Level 4: does a local registry lookup
4770          * Level 5: same as Level 2
4771          */
4772
4773         if (r->in.server && r->in.server[0] == '\0') {
4774                 r->in.server = NULL;
4775         }
4776
4777         switch (r->in.level) {
4778         case 0:
4779                 result = enumprinters_level0(p->mem_ctx, session_info,
4780                                              p->msg_ctx, r->in.flags,
4781                                              r->in.server,
4782                                              r->out.info, r->out.count);
4783                 break;
4784         case 1:
4785                 result = enumprinters_level1(p->mem_ctx, session_info,
4786                                              p->msg_ctx, r->in.flags,
4787                                              r->in.server,
4788                                              r->out.info, r->out.count);
4789                 break;
4790         case 2:
4791                 result = enumprinters_level2(p->mem_ctx, session_info,
4792                                              p->msg_ctx, r->in.flags,
4793                                              r->in.server,
4794                                              r->out.info, r->out.count);
4795                 break;
4796         case 4:
4797                 result = enumprinters_level4(p->mem_ctx, session_info,
4798                                              p->msg_ctx, r->in.flags,
4799                                              r->in.server,
4800                                              r->out.info, r->out.count);
4801                 break;
4802         case 5:
4803                 result = enumprinters_level5(p->mem_ctx, session_info,
4804                                              p->msg_ctx, r->in.flags,
4805                                              r->in.server,
4806                                              r->out.info, r->out.count);
4807                 break;
4808         default:
4809                 return WERR_INVALID_LEVEL;
4810         }
4811
4812         if (!W_ERROR_IS_OK(result)) {
4813                 return result;
4814         }
4815
4816         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4817                                                      spoolss_EnumPrinters,
4818                                                      *r->out.info, r->in.level,
4819                                                      *r->out.count);
4820         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4821         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4822
4823         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4824 }
4825
4826 /****************************************************************
4827  _spoolss_GetPrinter
4828 ****************************************************************/
4829
4830 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4831                            struct spoolss_GetPrinter *r)
4832 {
4833         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4834         struct spoolss_PrinterInfo2 *info2 = NULL;
4835         WERROR result = WERR_OK;
4836         int snum;
4837
4838         /* that's an [in out] buffer */
4839
4840         if (!r->in.buffer && (r->in.offered != 0)) {
4841                 result = WERR_INVALID_PARAMETER;
4842                 goto err_info_free;
4843         }
4844
4845         *r->out.needed = 0;
4846
4847         if (Printer == NULL) {
4848                 result = WERR_INVALID_HANDLE;
4849                 goto err_info_free;
4850         }
4851
4852         if (Printer->printer_type == SPLHND_SERVER) {
4853
4854                 struct dcerpc_binding_handle *b;
4855
4856                 if (r->in.level != 3) {
4857                         result = WERR_INVALID_LEVEL;
4858                         goto err_info_free;
4859                 }
4860
4861                 result = winreg_printer_binding_handle(p->mem_ctx,
4862                                                        get_session_info_system(),
4863                                                        p->msg_ctx,
4864                                                        &b);
4865                 if (!W_ERROR_IS_OK(result)) {
4866                         goto err_info_free;
4867                 }
4868
4869                 result = winreg_get_printserver_secdesc(p->mem_ctx,
4870                                                         b,
4871                                                         &r->out.info->info3.secdesc);
4872                 if (!W_ERROR_IS_OK(result)) {
4873                         goto err_info_free;
4874                 }
4875
4876                 goto done;
4877         }
4878
4879         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4880                 result = WERR_INVALID_HANDLE;
4881                 goto err_info_free;
4882         }
4883
4884         result = winreg_get_printer_internal(p->mem_ctx,
4885                                     get_session_info_system(),
4886                                     p->msg_ctx,
4887                                     lp_const_servicename(snum),
4888                                     &info2);
4889         if (!W_ERROR_IS_OK(result)) {
4890                 goto err_info_free;
4891         }
4892
4893         switch (r->in.level) {
4894         case 0:
4895                 result = construct_printer_info0(p->mem_ctx,
4896                                                  get_session_info_system(),
4897                                                  p->msg_ctx,
4898                                                  info2,
4899                                                  Printer->servername,
4900                                                  &r->out.info->info0,
4901                                                  snum);
4902                 break;
4903         case 1:
4904                 result = construct_printer_info1(p->mem_ctx, info2,
4905                                                  PRINTER_ENUM_ICON8,
4906                                                  Printer->servername,
4907                                                  &r->out.info->info1, snum);
4908                 break;
4909         case 2:
4910                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4911                                                  Printer->servername,
4912                                                  &r->out.info->info2, snum);
4913                 break;
4914         case 3:
4915                 result = construct_printer_info3(p->mem_ctx, info2,
4916                                                  Printer->servername,
4917                                                  &r->out.info->info3, snum);
4918                 break;
4919         case 4:
4920                 result = construct_printer_info4(p->mem_ctx, info2,
4921                                                  Printer->servername,
4922                                                  &r->out.info->info4, snum);
4923                 break;
4924         case 5:
4925                 result = construct_printer_info5(p->mem_ctx, info2,
4926                                                  Printer->servername,
4927                                                  &r->out.info->info5, snum);
4928                 break;
4929         case 6:
4930                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4931                                                  Printer->servername,
4932                                                  &r->out.info->info6, snum);
4933                 break;
4934         case 7:
4935                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4936                                                  Printer->servername,
4937                                                  &r->out.info->info7, snum);
4938                 break;
4939         case 8:
4940                 result = construct_printer_info8(p->mem_ctx, info2,
4941                                                  Printer->servername,
4942                                                  &r->out.info->info8, snum);
4943                 break;
4944         default:
4945                 result = WERR_INVALID_LEVEL;
4946                 break;
4947         }
4948         TALLOC_FREE(info2);
4949
4950         if (!W_ERROR_IS_OK(result)) {
4951                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4952                           r->in.level, win_errstr(result)));
4953                 goto err_info_free;
4954         }
4955  done:
4956         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4957                                                r->out.info, r->in.level);
4958         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4959
4960         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4961
4962 err_info_free:
4963         TALLOC_FREE(r->out.info);
4964         return result;
4965 }
4966
4967 /********************************************************************
4968  ********************************************************************/
4969
4970 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4971         do { \
4972                 if (in && strlen(in)) { \
4973                         out = talloc_strdup(mem_ctx, in); \
4974                 } else { \
4975                         out = talloc_strdup(mem_ctx, ""); \
4976                 } \
4977                 W_ERROR_HAVE_NO_MEMORY(out); \
4978         } while (0);
4979
4980 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4981         do { \
4982                 if (in && strlen(in)) { \
4983                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4984                 } else { \
4985                         out = talloc_strdup(mem_ctx, ""); \
4986                 } \
4987                 W_ERROR_HAVE_NO_MEMORY(out); \
4988         } while (0);
4989
4990 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4991                                                   const char **string_array,
4992                                                   const char ***presult,
4993                                                   const char *cservername,
4994                                                   const char *arch,
4995                                                   int version)
4996 {
4997         int i;
4998         size_t num_strings = 0;
4999         const char **array = NULL;
5000
5001         if (string_array == NULL) {
5002                 return WERR_INVALID_PARAMETER;
5003         }
5004
5005         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
5006                 const char *str = NULL;
5007
5008                 if (cservername == NULL || arch == NULL) {
5009                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
5010                 } else {
5011                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
5012                 }
5013
5014                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
5015                         TALLOC_FREE(array);
5016                         return WERR_NOT_ENOUGH_MEMORY;
5017                 }
5018         }
5019
5020         if (i > 0) {
5021                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
5022                              &array, &num_strings);
5023         }
5024
5025         if (presult != NULL) {
5026                 *presult = array;
5027         } else {
5028                 talloc_free(array);
5029         }
5030
5031         return WERR_OK;
5032 }
5033
5034 /********************************************************************
5035  * fill a spoolss_DriverInfo1 struct
5036  ********************************************************************/
5037
5038 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
5039                                         struct spoolss_DriverInfo1 *r,
5040                                         const struct spoolss_DriverInfo8 *driver,
5041                                         const char *servername)
5042 {
5043         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5044         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5045
5046         return WERR_OK;
5047 }
5048
5049 /********************************************************************
5050  * fill a spoolss_DriverInfo2 struct
5051  ********************************************************************/
5052
5053 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5054                                         struct spoolss_DriverInfo2 *r,
5055                                         const struct spoolss_DriverInfo8 *driver,
5056                                         const char *servername)
5057
5058 {
5059         const char *cservername = canon_servername(servername);
5060
5061         r->version              = driver->version;
5062
5063         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5064         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5065         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5066         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5067
5068         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5069                                driver->architecture,
5070                                driver->version,
5071                                driver->driver_path,
5072                                r->driver_path);
5073
5074         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5075                                driver->architecture,
5076                                driver->version,
5077                                driver->data_file,
5078                                r->data_file);
5079
5080         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5081                                driver->architecture,
5082                                driver->version,
5083                                driver->config_file,
5084                                r->config_file);
5085
5086         return WERR_OK;
5087 }
5088
5089 /********************************************************************
5090  * fill a spoolss_DriverInfo3 struct
5091  ********************************************************************/
5092
5093 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5094                                         struct spoolss_DriverInfo3 *r,
5095                                         const struct spoolss_DriverInfo8 *driver,
5096                                         const char *servername)
5097 {
5098         const char *cservername = canon_servername(servername);
5099
5100         r->version              = driver->version;
5101
5102         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5103         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5104         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5105         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5106
5107         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5108                                driver->architecture,
5109                                driver->version,
5110                                driver->driver_path,
5111                                r->driver_path);
5112
5113         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5114                                driver->architecture,
5115                                driver->version,
5116                                driver->data_file,
5117                                r->data_file);
5118
5119         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5120                                driver->architecture,
5121                                driver->version,
5122                                driver->config_file,
5123                                r->config_file);
5124
5125         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5126                                driver->architecture,
5127                                driver->version,
5128                                driver->help_file,
5129                                r->help_file);
5130
5131         FILL_DRIVER_STRING(mem_ctx,
5132                            driver->monitor_name,
5133                            r->monitor_name);
5134
5135         FILL_DRIVER_STRING(mem_ctx,
5136                            driver->default_datatype,
5137                            r->default_datatype);
5138
5139         return string_array_from_driver_info(mem_ctx,
5140                                              driver->dependent_files,
5141                                              &r->dependent_files,
5142                                              cservername,
5143                                              driver->architecture,
5144                                              driver->version);
5145 }
5146
5147 /********************************************************************
5148  * fill a spoolss_DriverInfo4 struct
5149  ********************************************************************/
5150
5151 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5152                                         struct spoolss_DriverInfo4 *r,
5153                                         const struct spoolss_DriverInfo8 *driver,
5154                                         const char *servername)
5155 {
5156         const char *cservername = canon_servername(servername);
5157         WERROR result;
5158
5159         r->version              = driver->version;
5160
5161         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5162         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5163         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5164         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5165
5166         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5167                                driver->architecture,
5168                                driver->version,
5169                                driver->driver_path,
5170                                r->driver_path);
5171
5172         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5173                                driver->architecture,
5174                                driver->version,
5175                                driver->data_file,
5176                                r->data_file);
5177
5178         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5179                                driver->architecture,
5180                                driver->version,
5181                                driver->config_file,
5182                                r->config_file);
5183
5184         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5185                                driver->architecture,
5186                                driver->version,
5187                                driver->help_file,
5188                                r->help_file);
5189
5190         result = string_array_from_driver_info(mem_ctx,
5191                                                driver->dependent_files,
5192                                                &r->dependent_files,
5193                                                cservername,
5194                                                driver->architecture,
5195                                                driver->version);
5196         if (!W_ERROR_IS_OK(result)) {
5197                 return result;
5198         }
5199
5200         FILL_DRIVER_STRING(mem_ctx,
5201                            driver->monitor_name,
5202                            r->monitor_name);
5203
5204         FILL_DRIVER_STRING(mem_ctx,
5205                            driver->default_datatype,
5206                            r->default_datatype);
5207
5208
5209         result = string_array_from_driver_info(mem_ctx,
5210                                                driver->previous_names,
5211                                                &r->previous_names,
5212                                                NULL, NULL, 0);
5213
5214         return result;
5215 }
5216
5217 /********************************************************************
5218  * fill a spoolss_DriverInfo5 struct
5219  ********************************************************************/
5220
5221 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5222                                         struct spoolss_DriverInfo5 *r,
5223                                         const struct spoolss_DriverInfo8 *driver,
5224                                         const char *servername)
5225 {
5226         const char *cservername = canon_servername(servername);
5227
5228         r->version              = driver->version;
5229
5230         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5231         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5232         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5233         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5234
5235         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5236                                driver->architecture,
5237                                driver->version,
5238                                driver->driver_path,
5239                                r->driver_path);
5240
5241         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5242                                driver->architecture,
5243                                driver->version,
5244                                driver->data_file,
5245                                r->data_file);
5246
5247         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5248                                driver->architecture,
5249                                driver->version,
5250                                driver->config_file,
5251                                r->config_file);
5252
5253         r->driver_attributes    = 0;
5254         r->config_version       = 0;
5255         r->driver_version       = 0;
5256
5257         return WERR_OK;
5258 }
5259 /********************************************************************
5260  * fill a spoolss_DriverInfo6 struct
5261  ********************************************************************/
5262
5263 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5264                                         struct spoolss_DriverInfo6 *r,
5265                                         const struct spoolss_DriverInfo8 *driver,
5266                                         const char *servername)
5267 {
5268         const char *cservername = canon_servername(servername);
5269         WERROR result;
5270
5271         r->version              = driver->version;
5272
5273         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5274         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5275         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5276         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5277
5278         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5279                                driver->architecture,
5280                                driver->version,
5281                                driver->driver_path,
5282                                r->driver_path);
5283
5284         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5285                                driver->architecture,
5286                                driver->version,
5287                                driver->data_file,
5288                                r->data_file);
5289
5290         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5291                                driver->architecture,
5292                                driver->version,
5293                                driver->config_file,
5294                                r->config_file);
5295
5296         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5297                                driver->architecture,
5298                                driver->version,
5299                                driver->help_file,
5300                                r->help_file);
5301
5302         FILL_DRIVER_STRING(mem_ctx,
5303                            driver->monitor_name,
5304                            r->monitor_name);
5305
5306         FILL_DRIVER_STRING(mem_ctx,
5307                            driver->default_datatype,
5308                            r->default_datatype);
5309
5310         result = string_array_from_driver_info(mem_ctx,
5311                                                driver->dependent_files,
5312                                                &r->dependent_files,
5313                                                cservername,
5314                                                driver->architecture,
5315                                                driver->version);
5316         if (!W_ERROR_IS_OK(result)) {
5317                 return result;
5318         }
5319
5320         result = string_array_from_driver_info(mem_ctx,
5321                                                driver->previous_names,
5322                                                &r->previous_names,
5323                                                NULL, NULL, 0);
5324         if (!W_ERROR_IS_OK(result)) {
5325                 return result;
5326         }
5327
5328         r->driver_date          = driver->driver_date;
5329         r->driver_version       = driver->driver_version;
5330
5331         FILL_DRIVER_STRING(mem_ctx,
5332                            driver->manufacturer_name,
5333                            r->manufacturer_name);
5334         FILL_DRIVER_STRING(mem_ctx,
5335                            driver->manufacturer_url,
5336                            r->manufacturer_url);
5337         FILL_DRIVER_STRING(mem_ctx,
5338                            driver->hardware_id,
5339                            r->hardware_id);
5340         FILL_DRIVER_STRING(mem_ctx,
5341                            driver->provider,
5342                            r->provider);
5343
5344         return WERR_OK;
5345 }
5346
5347 /********************************************************************
5348  * fill a spoolss_DriverInfo8 struct
5349  ********************************************************************/
5350
5351 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5352                                         struct spoolss_DriverInfo8 *r,
5353                                         const struct spoolss_DriverInfo8 *driver,
5354                                         const char *servername)
5355 {
5356         const char *cservername = canon_servername(servername);
5357         WERROR result;
5358
5359         r->version              = driver->version;
5360
5361         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5362         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5363         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5364         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5365
5366         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5367                                driver->architecture,
5368                                driver->version,
5369                                driver->driver_path,
5370                                r->driver_path);
5371
5372         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5373                                driver->architecture,
5374                                driver->version,
5375                                driver->data_file,
5376                                r->data_file);
5377
5378         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5379                                driver->architecture,
5380                                driver->version,
5381                                driver->config_file,
5382                                r->config_file);
5383
5384         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5385                                driver->architecture,
5386                                driver->version,
5387                                driver->help_file,
5388                                r->help_file);
5389
5390         FILL_DRIVER_STRING(mem_ctx,
5391                            driver->monitor_name,
5392                            r->monitor_name);
5393
5394         FILL_DRIVER_STRING(mem_ctx,
5395                            driver->default_datatype,
5396                            r->default_datatype);
5397
5398         result = string_array_from_driver_info(mem_ctx,
5399                                                driver->dependent_files,
5400                                                &r->dependent_files,
5401                                                cservername,
5402                                                driver->architecture,
5403                                                driver->version);
5404         if (!W_ERROR_IS_OK(result)) {
5405                 return result;
5406         }
5407
5408         result = string_array_from_driver_info(mem_ctx,
5409                                                driver->previous_names,
5410                                                &r->previous_names,
5411                                                NULL, NULL, 0);
5412         if (!W_ERROR_IS_OK(result)) {
5413                 return result;
5414         }
5415
5416         r->driver_date          = driver->driver_date;
5417         r->driver_version       = driver->driver_version;
5418
5419         FILL_DRIVER_STRING(mem_ctx,
5420                            driver->manufacturer_name,
5421                            r->manufacturer_name);
5422         FILL_DRIVER_STRING(mem_ctx,
5423                            driver->manufacturer_url,
5424                            r->manufacturer_url);
5425         FILL_DRIVER_STRING(mem_ctx,
5426                            driver->hardware_id,
5427                            r->hardware_id);
5428         FILL_DRIVER_STRING(mem_ctx,
5429                            driver->provider,
5430                            r->provider);
5431
5432         FILL_DRIVER_STRING(mem_ctx,
5433                            driver->print_processor,
5434                            r->print_processor);
5435         FILL_DRIVER_STRING(mem_ctx,
5436                            driver->vendor_setup,
5437                            r->vendor_setup);
5438
5439         result = string_array_from_driver_info(mem_ctx,
5440                                                driver->color_profiles,
5441                                                &r->color_profiles,
5442                                                NULL, NULL, 0);
5443         if (!W_ERROR_IS_OK(result)) {
5444                 return result;
5445         }
5446
5447         FILL_DRIVER_STRING(mem_ctx,
5448                            driver->inf_path,
5449                            r->inf_path);
5450
5451         r->printer_driver_attributes    = driver->printer_driver_attributes;
5452
5453         result = string_array_from_driver_info(mem_ctx,
5454                                                driver->core_driver_dependencies,
5455                                                &r->core_driver_dependencies,
5456                                                NULL, NULL, 0);
5457         if (!W_ERROR_IS_OK(result)) {
5458                 return result;
5459         }
5460
5461         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5462         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5463
5464         return WERR_OK;
5465 }
5466
5467 #if 0 /* disabled until marshalling issues are resolved - gd */
5468 /********************************************************************
5469  ********************************************************************/
5470
5471 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5472                                           struct spoolss_DriverFileInfo *r,
5473                                           const char *cservername,
5474                                           const char *file_name,
5475                                           enum spoolss_DriverFileType file_type,
5476                                           uint32_t file_version)
5477 {
5478         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5479                                           cservername, file_name);
5480         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5481         r->file_type    = file_type;
5482         r->file_version = file_version;
5483
5484         return WERR_OK;
5485 }
5486
5487 /********************************************************************
5488  ********************************************************************/
5489
5490 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5491                                                  const struct spoolss_DriverInfo8 *driver,
5492                                                  const char *cservername,
5493                                                  struct spoolss_DriverFileInfo **info_p,
5494                                                  uint32_t *count_p)
5495 {
5496         struct spoolss_DriverFileInfo *info = NULL;
5497         uint32_t count = 0;
5498         WERROR result;
5499         uint32_t i;
5500
5501         *info_p = NULL;
5502         *count_p = 0;
5503
5504         if (strlen(driver->driver_path)) {
5505                 info = talloc_realloc(mem_ctx, info,
5506                                             struct spoolss_DriverFileInfo,
5507                                             count + 1);
5508                 W_ERROR_HAVE_NO_MEMORY(info);
5509                 result = fill_spoolss_DriverFileInfo(info,
5510                                                      &info[count],
5511                                                      cservername,
5512                                                      driver->driver_path,
5513                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5514                                                      0);
5515                 W_ERROR_NOT_OK_RETURN(result);
5516                 count++;
5517         }
5518
5519         if (strlen(driver->config_file)) {
5520                 info = talloc_realloc(mem_ctx, info,
5521                                             struct spoolss_DriverFileInfo,
5522                                             count + 1);
5523                 W_ERROR_HAVE_NO_MEMORY(info);
5524                 result = fill_spoolss_DriverFileInfo(info,
5525                                                      &info[count],
5526                                                      cservername,
5527                                                      driver->config_file,
5528                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5529                                                      0);
5530                 W_ERROR_NOT_OK_RETURN(result);
5531                 count++;
5532         }
5533
5534         if (strlen(driver->data_file)) {
5535                 info = talloc_realloc(mem_ctx, info,
5536                                             struct spoolss_DriverFileInfo,
5537                                             count + 1);
5538                 W_ERROR_HAVE_NO_MEMORY(info);
5539                 result = fill_spoolss_DriverFileInfo(info,
5540                                                      &info[count],
5541                                                      cservername,
5542                                                      driver->data_file,
5543                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5544                                                      0);
5545                 W_ERROR_NOT_OK_RETURN(result);
5546                 count++;
5547         }
5548
5549         if (strlen(driver->help_file)) {
5550                 info = talloc_realloc(mem_ctx, info,
5551                                             struct spoolss_DriverFileInfo,
5552                                             count + 1);
5553                 W_ERROR_HAVE_NO_MEMORY(info);
5554                 result = fill_spoolss_DriverFileInfo(info,
5555                                                      &info[count],
5556                                                      cservername,
5557                                                      driver->help_file,
5558                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5559                                                      0);
5560                 W_ERROR_NOT_OK_RETURN(result);
5561                 count++;
5562         }
5563
5564         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5565                 info = talloc_realloc(mem_ctx, info,
5566                                             struct spoolss_DriverFileInfo,
5567                                             count + 1);
5568                 W_ERROR_HAVE_NO_MEMORY(info);
5569                 result = fill_spoolss_DriverFileInfo(info,
5570                                                      &info[count],
5571                                                      cservername,
5572                                                      driver->dependent_files[i],
5573                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5574                                                      0);
5575                 W_ERROR_NOT_OK_RETURN(result);
5576                 count++;
5577         }
5578
5579         *info_p = info;
5580         *count_p = count;
5581
5582         return WERR_OK;
5583 }
5584
5585 /********************************************************************
5586  * fill a spoolss_DriverInfo101 struct
5587  ********************************************************************/
5588
5589 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5590                                           struct spoolss_DriverInfo101 *r,
5591                                           const struct spoolss_DriverInfo8 *driver,
5592                                           const char *servername)
5593 {
5594         const char *cservername = canon_servername(servername);
5595         WERROR result;
5596
5597         r->version              = driver->version;
5598
5599         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5600         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5601         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5602         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5603
5604         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5605                                                     cservername,
5606                                                     &r->file_info,
5607                                                     &r->file_count);
5608         if (!W_ERROR_IS_OK(result)) {
5609                 return result;
5610         }
5611
5612         FILL_DRIVER_STRING(mem_ctx,
5613                            driver->monitor_name,
5614                            r->monitor_name);
5615
5616         FILL_DRIVER_STRING(mem_ctx,
5617                            driver->default_datatype,
5618                            r->default_datatype);
5619
5620         result = string_array_from_driver_info(mem_ctx,
5621                                                driver->previous_names,
5622                                                &r->previous_names,
5623                                                NULL, NULL, 0);
5624         if (!W_ERROR_IS_OK(result)) {
5625                 return result;
5626         }
5627
5628         r->driver_date          = driver->driver_date;
5629         r->driver_version       = driver->driver_version;
5630
5631         FILL_DRIVER_STRING(mem_ctx,
5632                            driver->manufacturer_name,
5633                            r->manufacturer_name);
5634         FILL_DRIVER_STRING(mem_ctx,
5635                            driver->manufacturer_url,
5636                            r->manufacturer_url);
5637         FILL_DRIVER_STRING(mem_ctx,
5638                            driver->hardware_id,
5639                            r->hardware_id);
5640         FILL_DRIVER_STRING(mem_ctx,
5641                            driver->provider,
5642                            r->provider);
5643
5644         return WERR_OK;
5645 }
5646 #endif
5647 /********************************************************************
5648  ********************************************************************/
5649
5650 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5651                                                   const struct auth_session_info *session_info,
5652                                                   struct messaging_context *msg_ctx,
5653                                                   uint32_t level,
5654                                                   union spoolss_DriverInfo *r,
5655                                                   int snum,
5656                                                   const char *servername,
5657                                                   const char *architecture,
5658                                                   uint32_t version)
5659 {
5660         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5661         struct spoolss_DriverInfo8 *driver;
5662         WERROR result;
5663         struct dcerpc_binding_handle *b;
5664         TALLOC_CTX *tmp_ctx = NULL;
5665
5666         if (level == 101) {
5667                 return WERR_INVALID_LEVEL;
5668         }
5669
5670         tmp_ctx = talloc_new(mem_ctx);
5671         if (!tmp_ctx) {
5672                 return WERR_NOT_ENOUGH_MEMORY;
5673         }
5674
5675         result = winreg_printer_binding_handle(tmp_ctx,
5676                                                session_info,
5677                                                msg_ctx,
5678                                                &b);
5679         if (!W_ERROR_IS_OK(result)) {
5680                 goto done;
5681         }
5682
5683         result = winreg_get_printer(tmp_ctx, b,
5684                                     lp_const_servicename(snum),
5685                                     &pinfo2);
5686         if (!W_ERROR_IS_OK(result)) {
5687                 DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
5688                         lp_const_servicename(snum), win_errstr(result));
5689                 result = WERR_INVALID_PRINTER_NAME;
5690                 goto done;
5691         }
5692
5693         if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
5694                 return WERR_UNKNOWN_PRINTER_DRIVER;
5695         }
5696
5697         DBG_INFO("Construct printer driver [%s] for [%s]\n",
5698                  pinfo2->drivername,
5699                  pinfo2->sharename);
5700
5701         result = winreg_get_driver(tmp_ctx, b,
5702                                    architecture,
5703                                    pinfo2->drivername, version, &driver);
5704
5705         DBG_INFO("winreg_get_driver() status: %s\n",
5706                  win_errstr(result));
5707
5708         if (!W_ERROR_IS_OK(result)) {
5709                 /*
5710                  * Is this a W2k client ?
5711                  */
5712
5713                 if (version < 3) {
5714                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5715                         goto done;
5716                 }
5717
5718                 /* Yes - try again with a WinNT driver. */
5719                 version = 2;
5720                 result = winreg_get_driver(tmp_ctx, b,
5721                                            architecture,
5722                                            pinfo2->drivername,
5723                                            version, &driver);
5724                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5725                         win_errstr(result)));
5726                 if (!W_ERROR_IS_OK(result)) {
5727                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5728                         goto done;
5729                 }
5730         }
5731
5732         /* these are allocated on mem_ctx and not tmp_ctx because they are
5733          * the 'return value' and need to utlive this call */
5734         switch (level) {
5735         case 1:
5736                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5737                 break;
5738         case 2:
5739                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5740                 break;
5741         case 3:
5742                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5743                 break;
5744         case 4:
5745                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5746                 break;
5747         case 5:
5748                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5749                 break;
5750         case 6:
5751                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5752                 break;
5753         case 8:
5754                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5755                 break;
5756 #if 0 /* disabled until marshalling issues are resolved - gd */
5757         case 101:
5758                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5759                 break;
5760 #endif
5761         default:
5762                 result = WERR_INVALID_LEVEL;
5763                 break;
5764         }
5765
5766 done:
5767         talloc_free(tmp_ctx);
5768         return result;
5769 }
5770
5771 /****************************************************************
5772  _spoolss_GetPrinterDriver2
5773 ****************************************************************/
5774
5775 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5776                                   struct spoolss_GetPrinterDriver2 *r)
5777 {
5778         struct printer_handle *printer;
5779         WERROR result;
5780         uint32_t version = r->in.client_major_version;
5781
5782         int snum;
5783
5784         /* that's an [in out] buffer */
5785
5786         if (!r->in.buffer && (r->in.offered != 0)) {
5787                 result = WERR_INVALID_PARAMETER;
5788                 goto err_info_free;
5789         }
5790
5791         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5792
5793         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5794                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5795                 result = WERR_INVALID_PRINTER_NAME;
5796                 goto err_info_free;
5797         }
5798
5799         *r->out.needed = 0;
5800         *r->out.server_major_version = 0;
5801         *r->out.server_minor_version = 0;
5802
5803         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5804                 result = WERR_INVALID_HANDLE;
5805                 goto err_info_free;
5806         }
5807
5808         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5809                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5810                         "downgrading to v3\n"));
5811                 version = SPOOLSS_DRIVER_VERSION_200X;
5812         }
5813
5814         result = construct_printer_driver_info_level(p->mem_ctx,
5815                                                      get_session_info_system(),
5816                                                      p->msg_ctx,
5817                                                      r->in.level, r->out.info,
5818                                                      snum, printer->servername,
5819                                                      r->in.architecture,
5820                                                      version);
5821         if (!W_ERROR_IS_OK(result)) {
5822                 goto err_info_free;
5823         }
5824
5825         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5826                                                r->out.info, r->in.level);
5827         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5828
5829         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5830
5831 err_info_free:
5832         TALLOC_FREE(r->out.info);
5833         return result;
5834 }
5835
5836
5837 /****************************************************************
5838  _spoolss_StartPagePrinter
5839 ****************************************************************/
5840
5841 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5842                                  struct spoolss_StartPagePrinter *r)
5843 {
5844         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5845
5846         if (!Printer) {
5847                 DEBUG(3,("_spoolss_StartPagePrinter: "
5848                         "Error in startpageprinter printer handle\n"));
5849                 return WERR_INVALID_HANDLE;
5850         }
5851
5852         Printer->page_started = true;
5853         return WERR_OK;
5854 }
5855
5856 /****************************************************************
5857  _spoolss_EndPagePrinter
5858 ****************************************************************/
5859
5860 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5861                                struct spoolss_EndPagePrinter *r)
5862 {
5863         int snum;
5864
5865         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5866
5867         if (!Printer) {
5868                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5869                         OUR_HANDLE(r->in.handle)));
5870                 return WERR_INVALID_HANDLE;
5871         }
5872
5873         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5874                 return WERR_INVALID_HANDLE;
5875
5876         Printer->page_started = false;
5877         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5878
5879         return WERR_OK;
5880 }
5881
5882 /****************************************************************
5883  _spoolss_StartDocPrinter
5884 ****************************************************************/
5885
5886 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5887                                 struct spoolss_StartDocPrinter *r)
5888 {
5889         struct spoolss_DocumentInfo1 *info_1;
5890         int snum;
5891         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5892         WERROR werr;
5893         char *rhost;
5894         int rc;
5895
5896         if (!Printer) {
5897                 DEBUG(2,("_spoolss_StartDocPrinter: "
5898                         "Invalid handle (%s:%u:%u)\n",
5899                         OUR_HANDLE(r->in.handle)));
5900                 return WERR_INVALID_HANDLE;
5901         }
5902
5903         if (Printer->jobid) {
5904                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5905                           "StartDocPrinter called twice! "
5906                           "(existing jobid = %d)\n", Printer->jobid));
5907                 return WERR_INVALID_HANDLE;
5908         }
5909
5910         if (r->in.info_ctr->level != 1) {
5911                 return WERR_INVALID_LEVEL;
5912         }
5913
5914         info_1 = r->in.info_ctr->info.info1;
5915
5916         /*
5917          * a nice thing with NT is it doesn't listen to what you tell it.
5918          * when asked to send _only_ RAW datas, it tries to send datas
5919          * in EMF format.
5920          *
5921          * So I add checks like in NT Server ...
5922          */
5923
5924         if (info_1->datatype) {
5925                 /*
5926                  * The v4 driver model used in Windows 8 declares print jobs
5927                  * intended to bypass the XPS processing layer by setting
5928                  * datatype to "XPS_PASS" instead of "RAW".
5929                  */
5930                 if ((strcmp(info_1->datatype, "RAW") != 0)
5931                  && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5932                         *r->out.job_id = 0;
5933                         return WERR_INVALID_DATATYPE;
5934                 }
5935         }
5936
5937         /* get the share number of the printer */
5938         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5939                 return WERR_INVALID_HANDLE;
5940         }
5941
5942         rc = get_remote_hostname(p->remote_address,
5943                                  &rhost,
5944                                  p->mem_ctx);
5945         if (rc < 0) {
5946                 return WERR_NOT_ENOUGH_MEMORY;
5947         }
5948         if (strequal(rhost,"UNKNOWN")) {
5949                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5950                                                          p->mem_ctx);
5951                 if (rhost == NULL) {
5952                         return WERR_NOT_ENOUGH_MEMORY;
5953                 }
5954         }
5955
5956         werr = print_job_start(p->session_info,
5957                                p->msg_ctx,
5958                                rhost,
5959                                snum,
5960                                info_1->document_name,
5961                                info_1->output_file,
5962                                Printer->devmode,
5963                                &Printer->jobid);
5964
5965         /* An error occurred in print_job_start() so return an appropriate
5966            NT error code. */
5967
5968         if (!W_ERROR_IS_OK(werr)) {
5969                 return werr;
5970         }
5971
5972         Printer->document_started = true;
5973         *r->out.job_id = Printer->jobid;
5974
5975         return WERR_OK;
5976 }
5977
5978 /****************************************************************
5979  _spoolss_EndDocPrinter
5980 ****************************************************************/
5981
5982 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5983                               struct spoolss_EndDocPrinter *r)
5984 {
5985         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5986         NTSTATUS status;
5987         int snum;
5988
5989         if (!Printer) {
5990                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5991                         OUR_HANDLE(r->in.handle)));
5992                 return WERR_INVALID_HANDLE;
5993         }
5994
5995         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5996                 return WERR_INVALID_HANDLE;
5997         }
5998
5999         Printer->document_started = false;
6000         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
6001         if (!NT_STATUS_IS_OK(status)) {
6002                 DEBUG(2, ("_spoolss_EndDocPrinter: "
6003                           "print_job_end failed [%s]\n",
6004                           nt_errstr(status)));
6005         }
6006
6007         Printer->jobid = 0;
6008         return ntstatus_to_werror(status);
6009 }
6010
6011 /****************************************************************
6012  _spoolss_WritePrinter
6013 ****************************************************************/
6014
6015 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
6016                              struct spoolss_WritePrinter *r)
6017 {
6018         ssize_t buffer_written;
6019         int snum;
6020         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6021
6022         if (!Printer) {
6023                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
6024                         OUR_HANDLE(r->in.handle)));
6025                 *r->out.num_written = r->in._data_size;
6026                 return WERR_INVALID_HANDLE;
6027         }
6028
6029         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6030                 return WERR_INVALID_HANDLE;
6031
6032         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
6033         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
6034                                                    snum, Printer->jobid,
6035                                                    (const char *)r->in.data.data,
6036                                                    (size_t)r->in._data_size);
6037         if (buffer_written == (ssize_t)-1) {
6038                 *r->out.num_written = 0;
6039                 if (errno == ENOSPC)
6040                         return WERR_NO_SPOOL_SPACE;
6041                 else
6042                         return WERR_ACCESS_DENIED;
6043         }
6044
6045         *r->out.num_written = r->in._data_size;
6046
6047         return WERR_OK;
6048 }
6049
6050 /********************************************************************
6051  * api_spoolss_getprinter
6052  * called from the spoolss dispatcher
6053  *
6054  ********************************************************************/
6055
6056 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
6057                               struct pipes_struct *p)
6058 {
6059         const struct auth_session_info *session_info = p->session_info;
6060         int snum;
6061         WERROR errcode = WERR_INVALID_FUNCTION;
6062         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6063
6064         if (!Printer) {
6065                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
6066                         OUR_HANDLE(handle)));
6067                 return WERR_INVALID_HANDLE;
6068         }
6069
6070         if (!get_printer_snum(p, handle, &snum, NULL))
6071                 return WERR_INVALID_HANDLE;
6072
6073         switch (command) {
6074         case SPOOLSS_PRINTER_CONTROL_PAUSE:
6075                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
6076                 break;
6077         case SPOOLSS_PRINTER_CONTROL_RESUME:
6078         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6079                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6080                 break;
6081         case SPOOLSS_PRINTER_CONTROL_PURGE:
6082                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6083                 break;
6084         default:
6085                 return WERR_INVALID_LEVEL;
6086         }
6087
6088         return errcode;
6089 }
6090
6091
6092 /****************************************************************
6093  _spoolss_AbortPrinter
6094  * From MSDN: "Deletes printer's spool file if printer is configured
6095  * for spooling"
6096 ****************************************************************/
6097
6098 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6099                              struct spoolss_AbortPrinter *r)
6100 {
6101         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
6102         int             snum;
6103         WERROR          errcode = WERR_OK;
6104
6105         if (!Printer) {
6106                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6107                         OUR_HANDLE(r->in.handle)));
6108                 return WERR_INVALID_HANDLE;
6109         }
6110
6111         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6112                 return WERR_INVALID_HANDLE;
6113
6114         if (!Printer->document_started) {
6115                 return WERR_SPL_NO_STARTDOC;
6116         }
6117
6118         errcode = print_job_delete(p->session_info,
6119                                    p->msg_ctx,
6120                                    snum,
6121                                    Printer->jobid);
6122
6123         return errcode;
6124 }
6125
6126 /********************************************************************
6127  * called by spoolss_api_setprinter
6128  * when updating a printer description
6129  ********************************************************************/
6130
6131 static WERROR update_printer_sec(struct policy_handle *handle,
6132                                  struct pipes_struct *p,
6133                                  struct sec_desc_buf *secdesc_ctr)
6134 {
6135         struct spoolss_security_descriptor *new_secdesc = NULL;
6136         struct spoolss_security_descriptor *old_secdesc = NULL;
6137         const char *printer = NULL;
6138         WERROR result;
6139         int snum = -1;
6140         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6141         struct dcerpc_binding_handle *b;
6142         TALLOC_CTX *tmp_ctx = NULL;
6143         bool ok = false;
6144
6145         if (!Printer) {
6146                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6147                          OUR_HANDLE(handle)));
6148
6149                 result = WERR_INVALID_HANDLE;
6150                 goto done;
6151         }
6152
6153         if (secdesc_ctr == NULL) {
6154                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6155                 result = WERR_INVALID_PARAMETER;
6156                 goto done;
6157         }
6158
6159         switch (Printer->printer_type) {
6160         case SPLHND_SERVER:
6161                 break;
6162         case SPLHND_PRINTER:
6163                 if (!get_printer_snum(p, handle, &snum, NULL)) {
6164                         DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6165                                  OUR_HANDLE(handle)));
6166                         result = WERR_INVALID_HANDLE;
6167                         goto done;
6168                 }
6169                 printer = lp_const_servicename(snum);
6170                 break;
6171         default:
6172                 break;
6173         }
6174
6175         /* Check the user has permissions to change the security
6176            descriptor.  By experimentation with two NT machines, the user
6177            requires Full Access to the printer to change security
6178            information. */
6179
6180         switch (Printer->printer_type) {
6181         case SPLHND_SERVER:
6182                 ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
6183                 break;
6184         case SPLHND_PRINTER:
6185                 ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
6186                 break;
6187         default:
6188                 break;
6189         }
6190
6191         if (!ok) {
6192                 DEBUG(4,("update_printer_sec: updated denied by printer permissions "
6193                         "(access_granted: 0x%08x)\n", Printer->access_granted));
6194                 result = WERR_ACCESS_DENIED;
6195                 goto done;
6196         }
6197
6198         tmp_ctx = talloc_new(p->mem_ctx);
6199         if (!tmp_ctx) {
6200                 return WERR_NOT_ENOUGH_MEMORY;
6201         }
6202
6203         result = winreg_printer_binding_handle(tmp_ctx,
6204                                                get_session_info_system(),
6205                                                p->msg_ctx,
6206                                                &b);
6207         if (!W_ERROR_IS_OK(result)) {
6208                 goto done;
6209         }
6210
6211         /* NT seems to like setting the security descriptor even though
6212            nothing may have actually changed. */
6213
6214         if (printer != NULL) {
6215                 result = winreg_get_printer_secdesc(tmp_ctx, b,
6216                                                     printer,
6217                                                     &old_secdesc);
6218         } else {
6219                 result = winreg_get_printserver_secdesc(tmp_ctx, b,
6220                                                         &old_secdesc);
6221         }
6222         if (!W_ERROR_IS_OK(result)) {
6223                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6224                 result = WERR_INVALID_HANDLE;
6225                 goto done;
6226         }
6227
6228         if (DEBUGLEVEL >= 10) {
6229                 struct security_acl *the_acl;
6230                 int i;
6231
6232                 the_acl = old_secdesc->dacl;
6233                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6234                            printer, the_acl->num_aces));
6235
6236                 for (i = 0; i < the_acl->num_aces; i++) {
6237                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6238                                            &the_acl->aces[i].trustee),
6239                                   the_acl->aces[i].access_mask));
6240                 }
6241
6242                 the_acl = secdesc_ctr->sd->dacl;
6243
6244                 if (the_acl) {
6245                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6246                                    printer, the_acl->num_aces));
6247
6248                         for (i = 0; i < the_acl->num_aces; i++) {
6249                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6250                                                    &the_acl->aces[i].trustee),
6251                                            the_acl->aces[i].access_mask));
6252                         }
6253                 } else {
6254                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6255                 }
6256         }
6257
6258         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6259         if (new_secdesc == NULL) {
6260                 result = WERR_NOT_ENOUGH_MEMORY;
6261                 goto done;
6262         }
6263
6264         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6265                 result = WERR_OK;
6266                 goto done;
6267         }
6268
6269         if (printer != NULL) {
6270                 result = winreg_set_printer_secdesc(tmp_ctx, b,
6271                                                     printer,
6272                                                     new_secdesc);
6273         } else {
6274                 result = winreg_set_printserver_secdesc(tmp_ctx, b,
6275                                                         new_secdesc);
6276         }
6277
6278 done:
6279         talloc_free(tmp_ctx);
6280         return result;
6281 }
6282
6283 /********************************************************************
6284  Canonicalize printer info from a client
6285  ********************************************************************/
6286
6287 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6288                              struct spoolss_SetPrinterInfo2 *info2,
6289                              int snum)
6290 {
6291         fstring printername;
6292         const char *p;
6293
6294         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6295                 "portname=%s drivername=%s comment=%s location=%s\n",
6296                 info2->servername, info2->printername, info2->sharename,
6297                 info2->portname, info2->drivername, info2->comment,
6298                 info2->location));
6299
6300         /* we force some elements to "correct" values */
6301         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6302         if (info2->servername == NULL) {
6303                 return false;
6304         }
6305         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6306         if (info2->sharename == NULL) {
6307                 return false;
6308         }
6309
6310         /* check to see if we allow printername != sharename */
6311         if (lp_force_printername(snum)) {
6312                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6313                                         lp_netbios_name(), info2->sharename);
6314         } else {
6315                 /* make sure printername is in \\server\printername format */
6316                 fstrcpy(printername, info2->printername);
6317                 p = printername;
6318                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6319                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6320                                 p++;
6321                 }
6322
6323                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6324                                         lp_netbios_name(), p);
6325         }
6326         if (info2->printername == NULL) {
6327                 return false;
6328         }
6329
6330         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6331         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6332
6333         return true;
6334 }
6335
6336 /****************************************************************************
6337 ****************************************************************************/
6338
6339 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6340 {
6341         char *cmd = lp_addport_command(talloc_tos());
6342         char *command = NULL;
6343         int ret;
6344         bool is_print_op = false;
6345
6346         if ( !*cmd ) {
6347                 return WERR_ACCESS_DENIED;
6348         }
6349
6350         command = talloc_asprintf(ctx,
6351                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6352         if (!command) {
6353                 return WERR_NOT_ENOUGH_MEMORY;
6354         }
6355
6356         if ( token )
6357                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6358
6359         DEBUG(10,("Running [%s]\n", command));
6360
6361         /********* BEGIN SePrintOperatorPrivilege **********/
6362
6363         if ( is_print_op )
6364                 become_root();
6365
6366         ret = smbrun(command, NULL, NULL);
6367
6368         if ( is_print_op )
6369                 unbecome_root();
6370
6371         /********* END SePrintOperatorPrivilege **********/
6372
6373         DEBUGADD(10,("returned [%d]\n", ret));
6374
6375         TALLOC_FREE(command);
6376
6377         if ( ret != 0 ) {
6378                 return WERR_ACCESS_DENIED;
6379         }
6380
6381         return WERR_OK;
6382 }
6383
6384 /****************************************************************************
6385 ****************************************************************************/
6386
6387 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6388                                    int snum)
6389 {
6390         /*
6391          * As we do not know if we are embedded in the file server process
6392          * or not, we have to pretend that all shares are in use.
6393          */
6394         return true;
6395 }
6396
6397 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6398                              struct spoolss_SetPrinterInfo2 *info2,
6399                              const char *remote_machine,
6400                              struct messaging_context *msg_ctx)
6401 {
6402         char *cmd = lp_addprinter_command(talloc_tos());
6403         char **qlines;
6404         char *command = NULL;
6405         int numlines;
6406         int ret;
6407         int fd;
6408         bool is_print_op = false;
6409
6410         if (!remote_machine) {
6411                 return false;
6412         }
6413
6414         command = talloc_asprintf(ctx,
6415                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6416                         cmd, info2->printername, info2->sharename,
6417                         info2->portname, info2->drivername,
6418                         info2->location, info2->comment, remote_machine);
6419         if (!command) {
6420                 return false;
6421         }
6422
6423         if ( token )
6424                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6425
6426         DEBUG(10,("Running [%s]\n", command));
6427
6428         /********* BEGIN SePrintOperatorPrivilege **********/
6429
6430         if ( is_print_op )
6431                 become_root();
6432
6433         ret = smbrun(command, &fd, NULL);
6434         if (ret == 0) {
6435                 /* Tell everyone we updated smb.conf. */
6436                 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
6437         }
6438
6439         if ( is_print_op )
6440                 unbecome_root();
6441
6442         /********* END SePrintOperatorPrivilege **********/
6443
6444         DEBUGADD(10,("returned [%d]\n", ret));
6445
6446         TALLOC_FREE(command);
6447
6448         if ( ret != 0 ) {
6449                 if (fd != -1)
6450                         close(fd);
6451                 return false;
6452         }
6453
6454         /* reload our services immediately */
6455         become_root();
6456         reload_services(NULL, spoolss_conn_snum_used, false);
6457         unbecome_root();
6458
6459         numlines = 0;
6460         /* Get lines and convert them back to dos-codepage */
6461         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6462         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6463         close(fd);
6464
6465         /* Set the portname to what the script says the portname should be. */
6466         /* but don't require anything to be return from the script exit a good error code */
6467
6468         if (numlines) {
6469                 /* Set the portname to what the script says the portname should be. */
6470                 info2->portname = talloc_strdup(ctx, qlines[0]);
6471                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6472         }
6473
6474         TALLOC_FREE(qlines);
6475         return true;
6476 }
6477
6478 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6479                                const struct auth_session_info *session_info,
6480                                struct messaging_context *msg_ctx,
6481                                int snum,
6482                                struct spoolss_SetPrinterInfo2 *printer,
6483                                struct spoolss_PrinterInfo2 *old_printer)
6484 {
6485         bool force_update = (old_printer == NULL);
6486         const char *dnsdomname;
6487         const char *longname;
6488         const char *uncname;
6489         const char *spooling;
6490         DATA_BLOB buffer;
6491         WERROR result = WERR_OK;
6492         struct dcerpc_binding_handle *b;
6493         TALLOC_CTX *tmp_ctx;
6494         bool ok;
6495
6496         tmp_ctx = talloc_new(mem_ctx);
6497         if (!tmp_ctx) {
6498                 return WERR_NOT_ENOUGH_MEMORY;
6499         }
6500
6501         result = winreg_printer_binding_handle(tmp_ctx,
6502                                                session_info,
6503                                                msg_ctx,
6504                                                &b);
6505         if (!W_ERROR_IS_OK(result)) {
6506                 goto done;
6507         }
6508
6509         if (printer->drivername != NULL &&
6510             (force_update ||
6511              !strequal(printer->drivername, old_printer->drivername))) {
6512                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6513                 if (!ok) {
6514                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6515                         result = WERR_INVALID_DATA;
6516                         goto done;
6517                 }
6518                 result = winreg_set_printer_dataex(tmp_ctx, b,
6519                                           printer->sharename,
6520                                           SPOOL_DSSPOOLER_KEY,
6521                                           SPOOL_REG_DRIVERNAME,
6522                                           REG_SZ,
6523                                           buffer.data,
6524                                           buffer.length);
6525                 if (!W_ERROR_IS_OK(result)) {
6526                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6527                         goto done;
6528                 }
6529
6530                 if (!force_update) {
6531                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6532                                 printer->drivername));
6533
6534                         notify_printer_driver(server_event_context(), msg_ctx,
6535                                               snum, printer->drivername ?
6536                                               printer->drivername : "");
6537                 }
6538         }
6539
6540         if (printer->comment != NULL &&
6541             (force_update ||
6542              !strequal(printer->comment, old_printer->comment))) {
6543                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6544                 if (!ok) {
6545                         DEBUG(0, ("comment data corrupted\n"));
6546                         result = WERR_INVALID_DATA;
6547                         goto done;
6548                 }
6549                 result = winreg_set_printer_dataex(tmp_ctx, b,
6550                                           printer->sharename,
6551                                           SPOOL_DSSPOOLER_KEY,
6552                                           SPOOL_REG_DESCRIPTION,
6553                                           REG_SZ,
6554                                           buffer.data,
6555                                           buffer.length);
6556                 if (!W_ERROR_IS_OK(result)) {
6557                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6558                         goto done;
6559                 }
6560
6561                 if (!force_update) {
6562                         notify_printer_comment(server_event_context(), msg_ctx,
6563                                                snum, printer->comment ?
6564                                                printer->comment : "");
6565                 }
6566         }
6567
6568         if (printer->sharename != NULL &&
6569             (force_update ||
6570              !strequal(printer->sharename, old_printer->sharename))) {
6571                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6572                 if (!ok) {
6573                         DEBUG(0, ("sharename data corrupted\n"));
6574                         result = WERR_INVALID_DATA;
6575                         goto done;
6576                 }
6577                 result = winreg_set_printer_dataex(tmp_ctx, b,
6578                                           printer->sharename,
6579                                           SPOOL_DSSPOOLER_KEY,
6580                                           SPOOL_REG_PRINTSHARENAME,
6581                                           REG_SZ,
6582                                           buffer.data,
6583                                           buffer.length);
6584                 if (!W_ERROR_IS_OK(result)) {
6585                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6586                         goto done;
6587                 }
6588
6589                 if (!force_update) {
6590                         notify_printer_sharename(server_event_context(),
6591                                                  msg_ctx,
6592                                                  snum, printer->sharename ?
6593                                                  printer->sharename : "");
6594                 }
6595
6596                 /* name change, purge any cache entries for the old */
6597                 prune_printername_cache();
6598         }
6599
6600         if (printer->printername != NULL &&
6601             (force_update ||
6602              !strequal(printer->printername, old_printer->printername))) {
6603                 const char *p;
6604
6605                 p = strrchr(printer->printername, '\\' );
6606                 if (p != NULL) {
6607                         p++;
6608                 } else {
6609                         p = printer->printername;
6610                 }
6611
6612                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6613                 if (!ok) {
6614                         DEBUG(0, ("printername data corrupted\n"));
6615                         result = WERR_INVALID_DATA;
6616                         goto done;
6617                 }
6618                 result = winreg_set_printer_dataex(tmp_ctx, b,
6619                                           printer->sharename,
6620                                           SPOOL_DSSPOOLER_KEY,
6621                                           SPOOL_REG_PRINTERNAME,
6622                                           REG_SZ,
6623                                           buffer.data,
6624                                           buffer.length);
6625                 if (!W_ERROR_IS_OK(result)) {
6626                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6627                         goto done;
6628                 }
6629
6630                 if (!force_update) {
6631                         notify_printer_printername(server_event_context(),
6632                                                    msg_ctx, snum, p ? p : "");
6633                 }
6634
6635                 /* name change, purge any cache entries for the old */
6636                 prune_printername_cache();
6637         }
6638
6639         if (printer->portname != NULL &&
6640             (force_update ||
6641              !strequal(printer->portname, old_printer->portname))) {
6642                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6643                 if (!ok) {
6644                         DEBUG(0, ("portname data corrupted\n"));
6645                         result = WERR_INVALID_DATA;
6646                         goto done;
6647                 }
6648                 result = winreg_set_printer_dataex(tmp_ctx, b,
6649                                           printer->sharename,
6650                                           SPOOL_DSSPOOLER_KEY,
6651                                           SPOOL_REG_PORTNAME,
6652                                           REG_SZ,
6653                                           buffer.data,
6654                                           buffer.length);
6655                 if (!W_ERROR_IS_OK(result)) {
6656                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6657                         goto done;
6658                 }
6659
6660                 if (!force_update) {
6661                         notify_printer_port(server_event_context(),
6662                                             msg_ctx, snum, printer->portname ?
6663                                             printer->portname : "");
6664                 }
6665         }
6666
6667         if (printer->location != NULL &&
6668             (force_update ||
6669              !strequal(printer->location, old_printer->location))) {
6670                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6671                 if (!ok) {
6672                         DEBUG(0, ("location data corrupted\n"));
6673                         result = WERR_INVALID_DATA;
6674                         goto done;
6675                 }
6676                 result = winreg_set_printer_dataex(tmp_ctx, b,
6677                                           printer->sharename,
6678                                           SPOOL_DSSPOOLER_KEY,
6679                                           SPOOL_REG_LOCATION,
6680                                           REG_SZ,
6681                                           buffer.data,
6682                                           buffer.length);
6683                 if (!W_ERROR_IS_OK(result)) {
6684                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6685                         goto done;
6686                 }
6687
6688                 if (!force_update) {
6689                         notify_printer_location(server_event_context(),
6690                                                 msg_ctx, snum,
6691                                                 printer->location ?
6692                                                 printer->location : "");
6693                 }
6694         }
6695
6696         if (printer->sepfile != NULL &&
6697             (force_update ||
6698              !strequal(printer->sepfile, old_printer->sepfile))) {
6699                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6700                 if (!ok) {
6701                         DEBUG(0, ("sepfile data corrupted\n"));
6702                         result = WERR_INVALID_DATA;
6703                         goto done;
6704                 }
6705                 result = winreg_set_printer_dataex(tmp_ctx, b,
6706                                           printer->sharename,
6707                                           SPOOL_DSSPOOLER_KEY,
6708                                           SPOOL_REG_PRINTSEPARATORFILE,
6709                                           REG_SZ,
6710                                           buffer.data,
6711                                           buffer.length);
6712                 if (!W_ERROR_IS_OK(result)) {
6713                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6714                         goto done;
6715                 }
6716
6717                 if (!force_update) {
6718                         notify_printer_sepfile(server_event_context(),
6719                                                msg_ctx, snum,
6720                                                printer->sepfile ?
6721                                                printer->sepfile : "");
6722                 }
6723         }
6724
6725         if (printer->starttime != 0 &&
6726             (force_update ||
6727              printer->starttime != old_printer->starttime)) {
6728                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6729                 SIVAL(buffer.data, 0, printer->starttime);
6730                 result = winreg_set_printer_dataex(tmp_ctx, b,
6731                                           printer->sharename,
6732                                           SPOOL_DSSPOOLER_KEY,
6733                                           SPOOL_REG_PRINTSTARTTIME,
6734                                           REG_DWORD,
6735                                           buffer.data,
6736                                           buffer.length);
6737                 if (!W_ERROR_IS_OK(result)) {
6738                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6739                         goto done;
6740                 }
6741         }
6742
6743         if (printer->untiltime != 0 &&
6744             (force_update ||
6745              printer->untiltime != old_printer->untiltime)) {
6746                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6747                 SIVAL(buffer.data, 0, printer->untiltime);
6748                 result = winreg_set_printer_dataex(tmp_ctx, b,
6749                                           printer->sharename,
6750                                           SPOOL_DSSPOOLER_KEY,
6751                                           SPOOL_REG_PRINTENDTIME,
6752                                           REG_DWORD,
6753                                           buffer.data,
6754                                           buffer.length);
6755                 if (!W_ERROR_IS_OK(result)) {
6756                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6757                         goto done;
6758                 }
6759         }
6760
6761         if (force_update || printer->priority != old_printer->priority) {
6762                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6763                 SIVAL(buffer.data, 0, printer->priority);
6764                 result = winreg_set_printer_dataex(tmp_ctx, b,
6765                                           printer->sharename,
6766                                           SPOOL_DSSPOOLER_KEY,
6767                                           SPOOL_REG_PRIORITY,
6768                                           REG_DWORD,
6769                                           buffer.data,
6770                                           buffer.length);
6771                 if (!W_ERROR_IS_OK(result)) {
6772                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6773                         goto done;
6774                 }
6775         }
6776
6777         if (force_update || printer->attributes != old_printer->attributes) {
6778                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6779                 SIVAL(buffer.data, 0, (printer->attributes &
6780                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6781                 result = winreg_set_printer_dataex(tmp_ctx, b,
6782                                           printer->sharename,
6783                                           SPOOL_DSSPOOLER_KEY,
6784                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6785                                           REG_DWORD,
6786                                           buffer.data,
6787                                           buffer.length);
6788                 if (!W_ERROR_IS_OK(result)) {
6789                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6790                         goto done;
6791                 }
6792
6793                 switch (printer->attributes & 0x3) {
6794                         case 0:
6795                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6796                                 break;
6797                         case 1:
6798                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6799                                 break;
6800                         case 2:
6801                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6802                                 break;
6803                         default:
6804                                 spooling = "unknown";
6805                 }
6806                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6807                 if (!ok) {
6808                         DEBUG(0, ("printSpooling data corrupted\n"));
6809                         result = WERR_INVALID_DATA;
6810                         goto done;
6811                 }
6812                 winreg_set_printer_dataex(tmp_ctx, b,
6813                                           printer->sharename,
6814                                           SPOOL_DSSPOOLER_KEY,
6815                                           SPOOL_REG_PRINTSPOOLING,
6816                                           REG_SZ,
6817                                           buffer.data,
6818                                           buffer.length);
6819         }
6820
6821         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6822         if (!ok) {
6823                 DEBUG(0, ("shortServerName data corrupted\n"));
6824                 result = WERR_INVALID_DATA;
6825                 goto done;
6826         }
6827         result = winreg_set_printer_dataex(tmp_ctx, b,
6828                                   printer->sharename,
6829                                   SPOOL_DSSPOOLER_KEY,
6830                                   SPOOL_REG_SHORTSERVERNAME,
6831                                   REG_SZ,
6832                                   buffer.data,
6833                                   buffer.length);
6834         if (!W_ERROR_IS_OK(result)) {
6835                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6836                 goto done;
6837         }
6838
6839         dnsdomname = get_mydnsfullname();
6840         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6841                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6842         } else {
6843                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6844         }
6845         if (longname == NULL) {
6846                 result = WERR_NOT_ENOUGH_MEMORY;
6847                 goto done;
6848         }
6849
6850         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6851         if (!ok) {
6852                 DEBUG(0, ("longname data corrupted\n"));
6853                 result = WERR_INVALID_DATA;
6854                 goto done;
6855         }
6856         result = winreg_set_printer_dataex(tmp_ctx, b,
6857                                            printer->sharename,
6858                                            SPOOL_DSSPOOLER_KEY,
6859                                            SPOOL_REG_SERVERNAME,
6860                                            REG_SZ,
6861                                            buffer.data,
6862                                            buffer.length);
6863         if (!W_ERROR_IS_OK(result)) {
6864                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6865                 goto done;
6866         }
6867
6868         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6869                                   lp_netbios_name(), printer->sharename);
6870         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6871         if (!ok) {
6872                 DEBUG(0, ("uncName data corrupted\n"));
6873                 result = WERR_INVALID_DATA;
6874                 goto done;
6875         }
6876         result = winreg_set_printer_dataex(tmp_ctx, b,
6877                                   printer->sharename,
6878                                   SPOOL_DSSPOOLER_KEY,
6879                                   SPOOL_REG_UNCNAME,
6880                                   REG_SZ,
6881                                   buffer.data,
6882                                   buffer.length);
6883         if (!W_ERROR_IS_OK(result)) {
6884                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6885                 goto done;
6886         }
6887
6888 done:
6889         talloc_free(tmp_ctx);
6890         return result;
6891 }
6892
6893 /********************************************************************
6894  * Called by spoolss_api_setprinter
6895  * when updating a printer description.
6896  ********************************************************************/
6897
6898 static WERROR update_printer(struct pipes_struct *p,
6899                              struct policy_handle *handle,
6900                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6901                              struct spoolss_DeviceMode *devmode)
6902 {
6903         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6904         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6905         struct spoolss_PrinterInfo2 *old_printer;
6906         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6907         int snum;
6908         WERROR result = WERR_OK;
6909         TALLOC_CTX *tmp_ctx;
6910         struct dcerpc_binding_handle *b;
6911
6912         DEBUG(8,("update_printer\n"));
6913
6914         tmp_ctx = talloc_new(p->mem_ctx);
6915         if (tmp_ctx == NULL) {
6916                 return WERR_NOT_ENOUGH_MEMORY;
6917         }
6918
6919         if (!Printer) {
6920                 result = WERR_INVALID_HANDLE;
6921                 goto done;
6922         }
6923
6924         if (!get_printer_snum(p, handle, &snum, NULL)) {
6925                 result = WERR_INVALID_HANDLE;
6926                 goto done;
6927         }
6928
6929         result = winreg_printer_binding_handle(tmp_ctx,
6930                                                get_session_info_system(),
6931                                                p->msg_ctx,
6932                                                &b);
6933         if (!W_ERROR_IS_OK(result)) {
6934                 goto done;
6935         }
6936
6937         result = winreg_get_printer(tmp_ctx, b,
6938                                     lp_const_servicename(snum),
6939                                     &old_printer);
6940         if (!W_ERROR_IS_OK(result)) {
6941                 result = WERR_INVALID_HANDLE;
6942                 goto done;
6943         }
6944
6945         /* Do sanity check on the requested changes for Samba */
6946         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6947                 result = WERR_INVALID_PARAMETER;
6948                 goto done;
6949         }
6950
6951         /* FIXME!!! If the driver has changed we really should verify that
6952            it is installed before doing much else   --jerry */
6953
6954         /* Check calling user has permission to update printer description */
6955         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6956                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6957                 result = WERR_ACCESS_DENIED;
6958                 goto done;
6959         }
6960
6961         /* Call addprinter hook */
6962         /* Check changes to see if this is really needed */
6963
6964         if (*lp_addprinter_command(talloc_tos()) &&
6965                         (!strequal(printer->drivername, old_printer->drivername) ||
6966                          !strequal(printer->comment, old_printer->comment) ||
6967                          !strequal(printer->portname, old_printer->portname) ||
6968                          !strequal(printer->location, old_printer->location)) )
6969         {
6970                 char *raddr;
6971
6972                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6973                                                          p->mem_ctx);
6974                 if (raddr == NULL) {
6975                         return WERR_NOT_ENOUGH_MEMORY;
6976                 }
6977
6978                 /* add_printer_hook() will call reload_services() */
6979                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6980                                       printer, raddr,
6981                                       p->msg_ctx)) {
6982                         result = WERR_ACCESS_DENIED;
6983                         goto done;
6984                 }
6985         }
6986
6987         result = update_dsspooler(tmp_ctx,
6988                                   get_session_info_system(),
6989                                   p->msg_ctx,
6990                                   snum,
6991                                   printer,
6992                                   old_printer);
6993         if (!W_ERROR_IS_OK(result)) {
6994                 goto done;
6995         }
6996
6997         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6998
6999         if (devmode == NULL) {
7000                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
7001         }
7002         result = winreg_update_printer(tmp_ctx, b,
7003                                        printer->sharename,
7004                                        printer_mask,
7005                                        printer,
7006                                        devmode,
7007                                        NULL);
7008
7009 done:
7010         talloc_free(tmp_ctx);
7011
7012         return result;
7013 }
7014
7015 /****************************************************************************
7016 ****************************************************************************/
7017 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
7018                                            struct policy_handle *handle,
7019                                            struct spoolss_SetPrinterInfo7 *info7)
7020 {
7021 #ifdef HAVE_ADS
7022         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7023         WERROR result;
7024         int snum;
7025         struct printer_handle *Printer;
7026
7027         if ( lp_security() != SEC_ADS ) {
7028                 return WERR_INVALID_LEVEL;
7029         }
7030
7031         Printer = find_printer_index_by_hnd(p, handle);
7032
7033         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
7034
7035         if (!Printer)
7036                 return WERR_INVALID_HANDLE;
7037
7038         if (!get_printer_snum(p, handle, &snum, NULL))
7039                 return WERR_INVALID_HANDLE;
7040
7041         result = winreg_get_printer_internal(p->mem_ctx,
7042                                     get_session_info_system(),
7043                                     p->msg_ctx,
7044                                     lp_servicename(talloc_tos(), snum),
7045                                     &pinfo2);
7046         if (!W_ERROR_IS_OK(result)) {
7047                 return WERR_INVALID_HANDLE;
7048         }
7049
7050         nt_printer_publish(pinfo2,
7051                            get_session_info_system(),
7052                            p->msg_ctx,
7053                            pinfo2,
7054                            info7->action);
7055
7056         TALLOC_FREE(pinfo2);
7057         return WERR_OK;
7058 #else
7059         return WERR_INVALID_LEVEL;
7060 #endif
7061 }
7062
7063 /********************************************************************
7064  ********************************************************************/
7065
7066 static WERROR update_printer_devmode(struct pipes_struct *p,
7067                                      struct policy_handle *handle,
7068                                      struct spoolss_DeviceMode *devmode)
7069 {
7070         int snum;
7071         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7072         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
7073
7074         DEBUG(8,("update_printer_devmode\n"));
7075
7076         if (!Printer) {
7077                 return WERR_INVALID_HANDLE;
7078         }
7079
7080         if (!get_printer_snum(p, handle, &snum, NULL)) {
7081                 return WERR_INVALID_HANDLE;
7082         }
7083
7084         /* Check calling user has permission to update printer description */
7085         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7086                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7087                 return WERR_ACCESS_DENIED;
7088         }
7089
7090         return winreg_update_printer_internal(p->mem_ctx,
7091                                      get_session_info_system(),
7092                                      p->msg_ctx,
7093                                      lp_const_servicename(snum),
7094                                      info2_mask,
7095                                      NULL,
7096                                      devmode,
7097                                      NULL);
7098 }
7099
7100
7101 /****************************************************************
7102  _spoolss_SetPrinter
7103 ****************************************************************/
7104
7105 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
7106                            struct spoolss_SetPrinter *r)
7107 {
7108         WERROR result;
7109
7110         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7111
7112         if (!Printer) {
7113                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
7114                         OUR_HANDLE(r->in.handle)));
7115                 return WERR_INVALID_HANDLE;
7116         }
7117
7118         /* check the level */
7119         switch (r->in.info_ctr->level) {
7120                 case 0:
7121                         return control_printer(r->in.handle, r->in.command, p);
7122                 case 2:
7123                         result = update_printer(p, r->in.handle,
7124                                                 r->in.info_ctr,
7125                                                 r->in.devmode_ctr->devmode);
7126                         if (!W_ERROR_IS_OK(result))
7127                                 return result;
7128                         if (r->in.secdesc_ctr->sd)
7129                                 result = update_printer_sec(r->in.handle, p,
7130                                                             r->in.secdesc_ctr);
7131                         return result;
7132                 case 3:
7133                         return update_printer_sec(r->in.handle, p,
7134                                                   r->in.secdesc_ctr);
7135                 case 4: {
7136                         struct spoolss_PrinterInfo2 *old_printer;
7137                         struct spoolss_SetPrinterInfo2 *set_old_printer;
7138                         struct spoolss_SetPrinterInfoCtr *info_ctr;
7139                         struct dcerpc_binding_handle *b;
7140                         int snum;
7141                         TALLOC_CTX *tmp_ctx;
7142
7143                         tmp_ctx = talloc_new(p->mem_ctx);
7144                         if (tmp_ctx == NULL) {
7145                                 return WERR_NOT_ENOUGH_MEMORY;
7146                         }
7147
7148                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7149                                 TALLOC_FREE(tmp_ctx);
7150                                 return WERR_INVALID_HANDLE;
7151                         }
7152
7153                         result = winreg_printer_binding_handle(tmp_ctx,
7154                                                                get_session_info_system(),
7155                                                                p->msg_ctx,
7156                                                                &b);
7157                         if (!W_ERROR_IS_OK(result)) {
7158                                 TALLOC_FREE(tmp_ctx);
7159                                 return result;
7160                         }
7161
7162                         result = winreg_get_printer(tmp_ctx, b,
7163                                                     lp_const_servicename(snum),
7164                                                     &old_printer);
7165                         if (!W_ERROR_IS_OK(result)) {
7166                                 TALLOC_FREE(tmp_ctx);
7167                                 return WERR_INVALID_HANDLE;
7168                         }
7169
7170                         old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
7171                         if (old_printer->servername == NULL) {
7172                                 TALLOC_FREE(tmp_ctx);
7173                                 return WERR_NOT_ENOUGH_MEMORY;
7174                         }
7175
7176                         old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
7177                         if (old_printer->printername == NULL) {
7178                                 TALLOC_FREE(tmp_ctx);
7179                                 return WERR_NOT_ENOUGH_MEMORY;
7180                         }
7181
7182                         old_printer->attributes = r->in.info_ctr->info.info4->attributes;
7183
7184                         set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
7185                         if (set_old_printer == NULL) {
7186                                 TALLOC_FREE(tmp_ctx);
7187                                 return WERR_NOT_ENOUGH_MEMORY;
7188                         }
7189
7190                         spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
7191
7192                         info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
7193                         if (info_ctr == NULL) {
7194                                 TALLOC_FREE(tmp_ctx);
7195                                 return WERR_NOT_ENOUGH_MEMORY;
7196                         }
7197
7198                         info_ctr->level = 2;
7199                         info_ctr->info.info2 = set_old_printer;
7200
7201                         result = update_printer(p, r->in.handle,
7202                                                 info_ctr,
7203                                                 r->in.devmode_ctr->devmode);
7204
7205                         if (!W_ERROR_IS_OK(result)) {
7206                                 TALLOC_FREE(tmp_ctx);
7207                                 return result;
7208                         }
7209
7210                         if (r->in.secdesc_ctr->sd) {
7211                                 result = update_printer_sec(r->in.handle, p,
7212                                                             r->in.secdesc_ctr);
7213                         }
7214
7215                         TALLOC_FREE(tmp_ctx);
7216                         return result;
7217                 }
7218                 case 7:
7219                         return publish_or_unpublish_printer(p, r->in.handle,
7220                                                             r->in.info_ctr->info.info7);
7221                 case 8:
7222                         return update_printer_devmode(p, r->in.handle,
7223                                                       r->in.devmode_ctr->devmode);
7224                 default:
7225                         return WERR_INVALID_LEVEL;
7226         }
7227 }
7228
7229 /****************************************************************
7230  _spoolss_FindClosePrinterNotify
7231 ****************************************************************/
7232
7233 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7234                                        struct spoolss_FindClosePrinterNotify *r)
7235 {
7236         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7237
7238         if (!Printer) {
7239                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7240                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7241                 return WERR_INVALID_HANDLE;
7242         }
7243
7244         if (Printer->notify.cli_chan != NULL &&
7245             Printer->notify.cli_chan->active_connections > 0) {
7246                 int snum = -1;
7247
7248                 if (Printer->printer_type == SPLHND_PRINTER) {
7249                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7250                                 return WERR_INVALID_HANDLE;
7251                         }
7252                 }
7253
7254                 srv_spoolss_replycloseprinter(snum, Printer);
7255         }
7256
7257         Printer->notify.flags=0;
7258         Printer->notify.options=0;
7259         Printer->notify.localmachine[0]='\0';
7260         Printer->notify.printerlocal=0;
7261         TALLOC_FREE(Printer->notify.option);
7262
7263         return WERR_OK;
7264 }
7265
7266 /****************************************************************
7267  _spoolss_AddJob
7268 ****************************************************************/
7269
7270 WERROR _spoolss_AddJob(struct pipes_struct *p,
7271                        struct spoolss_AddJob *r)
7272 {
7273         if (!r->in.buffer && (r->in.offered != 0)) {
7274                 return WERR_INVALID_PARAMETER;
7275         }
7276
7277         /* this is what a NT server returns for AddJob. AddJob must fail on
7278          * non-local printers */
7279
7280         if (r->in.level != 1) {
7281                 return WERR_INVALID_LEVEL;
7282         }
7283
7284         return WERR_INVALID_PARAMETER;
7285 }
7286
7287 /****************************************************************************
7288 fill_job_info1
7289 ****************************************************************************/
7290
7291 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7292                              struct spoolss_JobInfo1 *r,
7293                              const print_queue_struct *queue,
7294                              uint32_t jobid,
7295                              int position, int snum,
7296                              struct spoolss_PrinterInfo2 *pinfo2)
7297 {
7298         struct tm *t;
7299
7300         t = gmtime(&queue->time);
7301
7302         r->job_id               = jobid;
7303
7304         r->printer_name         = lp_servicename(mem_ctx, snum);
7305         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7306         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7307         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7308         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7309         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7310         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7311         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7312         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7313         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7314         r->text_status          = talloc_strdup(mem_ctx, "");
7315         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7316
7317         r->status               = nt_printj_status(queue->status);
7318         r->priority             = queue->priority;
7319         r->position             = position;
7320         r->total_pages          = queue->page_count;
7321         r->pages_printed        = 0; /* ??? */
7322
7323         init_systemtime(&r->submitted, t);
7324
7325         return WERR_OK;
7326 }
7327
7328 /****************************************************************************
7329 fill_job_info2
7330 ****************************************************************************/
7331
7332 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7333                              struct spoolss_JobInfo2 *r,
7334                              const print_queue_struct *queue,
7335                              uint32_t jobid,
7336                              int position, int snum,
7337                              struct spoolss_PrinterInfo2 *pinfo2,
7338                              struct spoolss_DeviceMode *devmode)
7339 {
7340         struct tm *t;
7341
7342         t = gmtime(&queue->time);
7343
7344         r->job_id               = jobid;
7345
7346         r->printer_name         = lp_servicename(mem_ctx, snum);
7347         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7348         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7349         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7350         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7351         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7352         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7353         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7354         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7355         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7356         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7357         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7358         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7359         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7360         r->parameters           = talloc_strdup(mem_ctx, "");
7361         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7362         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7363         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7364
7365         r->devmode              = devmode;
7366
7367         r->text_status          = talloc_strdup(mem_ctx, "");
7368         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7369
7370         r->secdesc              = NULL;
7371
7372         r->status               = nt_printj_status(queue->status);
7373         r->priority             = queue->priority;
7374         r->position             = position;
7375         r->start_time           = 0;
7376         r->until_time           = 0;
7377         r->total_pages          = queue->page_count;
7378         r->size                 = queue->size;
7379         init_systemtime(&r->submitted, t);
7380         r->time                 = 0;
7381         r->pages_printed        = 0; /* ??? */
7382
7383         return WERR_OK;
7384 }
7385
7386 /****************************************************************************
7387  Enumjobs at level 1.
7388 ****************************************************************************/
7389
7390 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7391                               const print_queue_struct *queue,
7392                               uint32_t num_queues, int snum,
7393                               struct spoolss_PrinterInfo2 *pinfo2,
7394                               union spoolss_JobInfo **info_p,
7395                               uint32_t *count)
7396 {
7397         union spoolss_JobInfo *info;
7398         int i;
7399         WERROR result = WERR_OK;
7400         uint32_t num_filled;
7401         struct tdb_print_db *pdb;
7402
7403         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7404         if (info == NULL) {
7405                 result = WERR_NOT_ENOUGH_MEMORY;
7406                 goto err_out;
7407         }
7408
7409         pdb = get_print_db_byname(pinfo2->sharename);
7410         if (pdb == NULL) {
7411                 result = WERR_INVALID_PARAMETER;
7412                 goto err_info_free;
7413         }
7414
7415         num_filled = 0;
7416         for (i = 0; i < num_queues; i++) {
7417                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7418                 if (jobid == (uint32_t)-1) {
7419                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7420                         continue;
7421                 }
7422
7423                 result = fill_job_info1(info,
7424                                         &info[num_filled].info1,
7425                                         &queue[i],
7426                                         jobid,
7427                                         i,
7428                                         snum,
7429                                         pinfo2);
7430                 if (!W_ERROR_IS_OK(result)) {
7431                         goto err_pdb_drop;
7432                 }
7433
7434                 num_filled++;
7435         }
7436
7437         release_print_db(pdb);
7438         *info_p = info;
7439         *count = num_filled;
7440
7441         return WERR_OK;
7442
7443 err_pdb_drop:
7444         release_print_db(pdb);
7445 err_info_free:
7446         TALLOC_FREE(info);
7447 err_out:
7448         *count = 0;
7449         return result;
7450 }
7451
7452 /****************************************************************************
7453  Enumjobs at level 2.
7454 ****************************************************************************/
7455
7456 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7457                               const print_queue_struct *queue,
7458                               uint32_t num_queues, int snum,
7459                               struct spoolss_PrinterInfo2 *pinfo2,
7460                               union spoolss_JobInfo **info_p,
7461                               uint32_t *count)
7462 {
7463         union spoolss_JobInfo *info;
7464         int i;
7465         WERROR result = WERR_OK;
7466         uint32_t num_filled;
7467         struct tdb_print_db *pdb;
7468
7469         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7470         if (info == NULL) {
7471                 result = WERR_NOT_ENOUGH_MEMORY;
7472                 goto err_out;
7473         }
7474
7475         pdb = get_print_db_byname(pinfo2->sharename);
7476         if (pdb == NULL) {
7477                 result = WERR_INVALID_PARAMETER;
7478                 goto err_info_free;
7479         }
7480
7481         num_filled = 0;
7482         for (i = 0; i< num_queues; i++) {
7483                 struct spoolss_DeviceMode *devmode;
7484                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7485                 if (jobid == (uint32_t)-1) {
7486                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7487                         continue;
7488                 }
7489
7490                 result = spoolss_create_default_devmode(info,
7491                                                         pinfo2->printername,
7492                                                         &devmode);
7493                 if (!W_ERROR_IS_OK(result)) {
7494                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7495                         goto err_pdb_drop;
7496                 }
7497
7498                 result = fill_job_info2(info,
7499                                         &info[num_filled].info2,
7500                                         &queue[i],
7501                                         jobid,
7502                                         i,
7503                                         snum,
7504                                         pinfo2,
7505                                         devmode);
7506                 if (!W_ERROR_IS_OK(result)) {
7507                         goto err_pdb_drop;
7508                 }
7509                 num_filled++;
7510         }
7511
7512         release_print_db(pdb);
7513         *info_p = info;
7514         *count = num_filled;
7515
7516         return WERR_OK;
7517
7518 err_pdb_drop:
7519         release_print_db(pdb);
7520 err_info_free:
7521         TALLOC_FREE(info);
7522 err_out:
7523         *count = 0;
7524         return result;
7525 }
7526
7527 /****************************************************************************
7528  Enumjobs at level 3.
7529 ****************************************************************************/
7530
7531 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7532                               const print_queue_struct *queue,
7533                               uint32_t num_queues, int snum,
7534                               struct spoolss_PrinterInfo2 *pinfo2,
7535                               union spoolss_JobInfo **info_p,
7536                               uint32_t *count)
7537 {
7538         union spoolss_JobInfo *info;
7539         int i;
7540         WERROR result = WERR_OK;
7541         uint32_t num_filled;
7542         struct tdb_print_db *pdb;
7543
7544         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7545         if (info == NULL) {
7546                 result = WERR_NOT_ENOUGH_MEMORY;
7547                 goto err_out;
7548         }
7549
7550         pdb = get_print_db_byname(pinfo2->sharename);
7551         if (pdb == NULL) {
7552                 result = WERR_INVALID_PARAMETER;
7553                 goto err_info_free;
7554         }
7555
7556         num_filled = 0;
7557         for (i = 0; i < num_queues; i++) {
7558                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7559                 if (jobid == (uint32_t)-1) {
7560                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7561                         continue;
7562                 }
7563
7564                 info[num_filled].info3.job_id = jobid;
7565                 /* next_job_id is overwritten on next iteration */
7566                 info[num_filled].info3.next_job_id = 0;
7567                 info[num_filled].info3.reserved = 0;
7568
7569                 if (num_filled > 0) {
7570                         info[num_filled - 1].info3.next_job_id = jobid;
7571                 }
7572                 num_filled++;
7573         }
7574
7575         release_print_db(pdb);
7576         *info_p = info;
7577         *count = num_filled;
7578
7579         return WERR_OK;
7580
7581 err_info_free:
7582         TALLOC_FREE(info);
7583 err_out:
7584         *count = 0;
7585         return result;
7586 }
7587
7588 /****************************************************************
7589  _spoolss_EnumJobs
7590 ****************************************************************/
7591
7592 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7593                          struct spoolss_EnumJobs *r)
7594 {
7595         WERROR result;
7596         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7597         int snum;
7598         print_status_struct prt_status;
7599         print_queue_struct *queue = NULL;
7600         uint32_t count;
7601
7602         /* that's an [in out] buffer */
7603
7604         if (!r->in.buffer && (r->in.offered != 0)) {
7605                 return WERR_INVALID_PARAMETER;
7606         }
7607
7608         if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7609                 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7610                 return WERR_INVALID_LEVEL;
7611         }
7612
7613         DEBUG(4,("_spoolss_EnumJobs\n"));
7614
7615         *r->out.needed = 0;
7616         *r->out.count = 0;
7617         *r->out.info = NULL;
7618
7619         /* lookup the printer snum and tdb entry */
7620
7621         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7622                 return WERR_INVALID_HANDLE;
7623         }
7624
7625         result = winreg_get_printer_internal(p->mem_ctx,
7626                                     get_session_info_system(),
7627                                     p->msg_ctx,
7628                                     lp_const_servicename(snum),
7629                                     &pinfo2);
7630         if (!W_ERROR_IS_OK(result)) {
7631                 return result;
7632         }
7633
7634         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7635         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7636                 count, prt_status.status, prt_status.message));
7637
7638         if (count == 0) {
7639                 SAFE_FREE(queue);
7640                 TALLOC_FREE(pinfo2);
7641                 return WERR_OK;
7642         }
7643
7644         switch (r->in.level) {
7645         case 1:
7646                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7647                                          pinfo2, r->out.info, r->out.count);
7648                 break;
7649         case 2:
7650                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7651                                          pinfo2, r->out.info, r->out.count);
7652                 break;
7653         case 3:
7654                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7655                                          pinfo2, r->out.info, r->out.count);
7656                 break;
7657         default:
7658                 SMB_ASSERT(false);      /* level checked on entry */
7659                 break;
7660         }
7661
7662         SAFE_FREE(queue);
7663         TALLOC_FREE(pinfo2);
7664
7665         if (!W_ERROR_IS_OK(result)) {
7666                 return result;
7667         }
7668
7669         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7670                                                      spoolss_EnumJobs,
7671                                                      *r->out.info, r->in.level,
7672                                                      *r->out.count);
7673         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7674         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7675
7676         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7677 }
7678
7679 /****************************************************************
7680  _spoolss_ScheduleJob
7681 ****************************************************************/
7682
7683 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7684                             struct spoolss_ScheduleJob *r)
7685 {
7686         return WERR_OK;
7687 }
7688
7689 /****************************************************************
7690 ****************************************************************/
7691
7692 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7693                                struct messaging_context *msg_ctx,
7694                                const char *printer_name,
7695                                uint32_t job_id,
7696                                struct spoolss_SetJobInfo1 *r)
7697 {
7698         char *old_doc_name;
7699
7700         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7701                 return WERR_INVALID_HANDLE;
7702         }
7703
7704         if (strequal(old_doc_name, r->document_name)) {
7705                 return WERR_OK;
7706         }
7707
7708         if (!print_job_set_name(server_event_context(), msg_ctx,
7709                                 printer_name, job_id, r->document_name)) {
7710                 return WERR_INVALID_HANDLE;
7711         }
7712
7713         return WERR_OK;
7714 }
7715
7716 /****************************************************************
7717  _spoolss_SetJob
7718 ****************************************************************/
7719
7720 WERROR _spoolss_SetJob(struct pipes_struct *p,
7721                        struct spoolss_SetJob *r)
7722 {
7723         const struct auth_session_info *session_info = p->session_info;
7724         int snum;
7725         WERROR errcode = WERR_INVALID_FUNCTION;
7726
7727         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7728                 return WERR_INVALID_HANDLE;
7729         }
7730
7731         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7732                 return WERR_INVALID_PRINTER_NAME;
7733         }
7734
7735         switch (r->in.command) {
7736         case SPOOLSS_JOB_CONTROL_CANCEL:
7737         case SPOOLSS_JOB_CONTROL_DELETE:
7738                 errcode = print_job_delete(session_info, p->msg_ctx,
7739                                            snum, r->in.job_id);
7740                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7741                         errcode = WERR_OK;
7742                 }
7743                 break;
7744         case SPOOLSS_JOB_CONTROL_PAUSE:
7745                 errcode = print_job_pause(session_info, p->msg_ctx,
7746                                           snum, r->in.job_id);
7747                 break;
7748         case SPOOLSS_JOB_CONTROL_RESTART:
7749         case SPOOLSS_JOB_CONTROL_RESUME:
7750                 errcode = print_job_resume(session_info, p->msg_ctx,
7751                                            snum, r->in.job_id);
7752                 break;
7753         case SPOOLSS_JOB_CONTROL_NOOP:
7754                 errcode = WERR_OK;
7755                 break;
7756         default:
7757                 return WERR_INVALID_LEVEL;
7758         }
7759
7760         if (!W_ERROR_IS_OK(errcode)) {
7761                 return errcode;
7762         }
7763
7764         if (r->in.ctr == NULL) {
7765                 return errcode;
7766         }
7767
7768         switch (r->in.ctr->level) {
7769         case 1:
7770                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7771                                            lp_const_servicename(snum),
7772                                            r->in.job_id,
7773                                            r->in.ctr->info.info1);
7774                 break;
7775         case 2:
7776         case 3:
7777         case 4:
7778         default:
7779                 return WERR_INVALID_LEVEL;
7780         }
7781
7782         return errcode;
7783 }
7784
7785 /****************************************************************************
7786  Enumerates all printer drivers by level and architecture.
7787 ****************************************************************************/
7788
7789 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7790                                                        const struct auth_session_info *session_info,
7791                                                        struct messaging_context *msg_ctx,
7792                                                        const char *servername,
7793                                                        const char *architecture,
7794                                                        uint32_t level,
7795                                                        union spoolss_DriverInfo **info_p,
7796                                                        uint32_t *count_p)
7797 {
7798         int i;
7799         uint32_t version;
7800         struct spoolss_DriverInfo8 *driver;
7801         union spoolss_DriverInfo *info = NULL;
7802         uint32_t count = 0;
7803         WERROR result = WERR_OK;
7804         uint32_t num_drivers;
7805         const char **drivers;
7806         struct dcerpc_binding_handle *b;
7807         TALLOC_CTX *tmp_ctx = NULL;
7808
7809         *count_p = 0;
7810         *info_p = NULL;
7811
7812         tmp_ctx = talloc_new(mem_ctx);
7813         if (!tmp_ctx) {
7814                 return WERR_NOT_ENOUGH_MEMORY;
7815         }
7816
7817         result = winreg_printer_binding_handle(tmp_ctx,
7818                                                session_info,
7819                                                msg_ctx,
7820                                                &b);
7821         if (!W_ERROR_IS_OK(result)) {
7822                 goto out;
7823         }
7824
7825         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7826                 result = winreg_get_driver_list(tmp_ctx, b,
7827                                                 architecture, version,
7828                                                 &num_drivers, &drivers);
7829                 if (!W_ERROR_IS_OK(result)) {
7830                         goto out;
7831                 }
7832                 DEBUG(4, ("we have:[%d] drivers in environment"
7833                           " [%s] and version [%d]\n",
7834                           num_drivers, architecture, version));
7835
7836                 if (num_drivers != 0) {
7837                         info = talloc_realloc(tmp_ctx, info,
7838                                                     union spoolss_DriverInfo,
7839                                                     count + num_drivers);
7840                         if (!info) {
7841                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7842                                         "failed to enlarge driver info buffer!\n"));
7843                                 result = WERR_NOT_ENOUGH_MEMORY;
7844                                 goto out;
7845                         }
7846                 }
7847
7848                 for (i = 0; i < num_drivers; i++) {
7849                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7850
7851                         result = winreg_get_driver(tmp_ctx, b,
7852                                                    architecture, drivers[i],
7853                                                    version, &driver);
7854                         if (!W_ERROR_IS_OK(result)) {
7855                                 goto out;
7856                         }
7857
7858                         switch (level) {
7859                         case 1:
7860                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7861                                                                    driver, servername);
7862                                 break;
7863                         case 2:
7864                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7865                                                                    driver, servername);
7866                                 break;
7867                         case 3:
7868                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7869                                                                    driver, servername);
7870                                 break;
7871                         case 4:
7872                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7873                                                                    driver, servername);
7874                                 break;
7875                         case 5:
7876                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7877                                                                    driver, servername);
7878                                 break;
7879                         case 6:
7880                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7881                                                                    driver, servername);
7882                                 break;
7883                         case 8:
7884                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7885                                                                    driver, servername);
7886                                 break;
7887                         default:
7888                                 result = WERR_INVALID_LEVEL;
7889                                 break;
7890                         }
7891
7892                         TALLOC_FREE(driver);
7893
7894                         if (!W_ERROR_IS_OK(result)) {
7895                                 goto out;
7896                         }
7897                 }
7898
7899                 count += num_drivers;
7900                 TALLOC_FREE(drivers);
7901         }
7902
7903 out:
7904         if (W_ERROR_IS_OK(result)) {
7905                 *info_p = talloc_move(mem_ctx, &info);
7906                 *count_p = count;
7907         }
7908
7909         talloc_free(tmp_ctx);
7910         return result;
7911 }
7912
7913 /****************************************************************************
7914  Enumerates all printer drivers by level.
7915 ****************************************************************************/
7916
7917 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7918                                        const struct auth_session_info *session_info,
7919                                        struct messaging_context *msg_ctx,
7920                                        const char *servername,
7921                                        const char *architecture,
7922                                        uint32_t level,
7923                                        union spoolss_DriverInfo **info_p,
7924                                        uint32_t *count_p)
7925 {
7926         uint32_t a,i;
7927         WERROR result = WERR_OK;
7928
7929         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7930
7931                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7932
7933                         union spoolss_DriverInfo *info = NULL;
7934                         uint32_t count = 0;
7935
7936                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7937                                                                           session_info,
7938                                                                           msg_ctx,
7939                                                                           servername,
7940                                                                           archi_table[a].long_archi,
7941                                                                           level,
7942                                                                           &info,
7943                                                                           &count);
7944                         if (!W_ERROR_IS_OK(result)) {
7945                                 continue;
7946                         }
7947
7948                         for (i=0; i < count; i++) {
7949                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7950                                              info[i], info_p, count_p);
7951                         }
7952                 }
7953
7954                 return result;
7955         }
7956
7957         return enumprinterdrivers_level_by_architecture(mem_ctx,
7958                                                         session_info,
7959                                                         msg_ctx,
7960                                                         servername,
7961                                                         architecture,
7962                                                         level,
7963                                                         info_p,
7964                                                         count_p);
7965 }
7966
7967 /****************************************************************
7968  _spoolss_EnumPrinterDrivers
7969 ****************************************************************/
7970
7971 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7972                                    struct spoolss_EnumPrinterDrivers *r)
7973 {
7974         const char *cservername;
7975         WERROR result;
7976
7977         /* that's an [in out] buffer */
7978
7979         if (!r->in.buffer && (r->in.offered != 0)) {
7980                 return WERR_INVALID_PARAMETER;
7981         }
7982
7983         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7984
7985         *r->out.needed = 0;
7986         *r->out.count = 0;
7987         *r->out.info = NULL;
7988
7989         cservername = canon_servername(r->in.server);
7990
7991         if (!is_myname_or_ipaddr(cservername)) {
7992                 return WERR_UNKNOWN_PRINTER_DRIVER;
7993         }
7994
7995         result = enumprinterdrivers_level(p->mem_ctx,
7996                                           get_session_info_system(),
7997                                           p->msg_ctx,
7998                                           cservername,
7999                                           r->in.environment,
8000                                           r->in.level,
8001                                           r->out.info,
8002                                           r->out.count);
8003         if (!W_ERROR_IS_OK(result)) {
8004                 return result;
8005         }
8006
8007         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8008                                                      spoolss_EnumPrinterDrivers,
8009                                                      *r->out.info, r->in.level,
8010                                                      *r->out.count);
8011         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8012         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8013
8014         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8015 }
8016
8017 /****************************************************************
8018  _spoolss_EnumForms
8019 ****************************************************************/
8020
8021 WERROR _spoolss_EnumForms(struct pipes_struct *p,
8022                           struct spoolss_EnumForms *r)
8023 {
8024         WERROR result;
8025
8026         *r->out.count = 0;
8027         *r->out.needed = 0;
8028         *r->out.info = NULL;
8029
8030         /* that's an [in out] buffer */
8031
8032         if (!r->in.buffer && (r->in.offered != 0) ) {
8033                 return WERR_INVALID_PARAMETER;
8034         }
8035
8036         DEBUG(4,("_spoolss_EnumForms\n"));
8037         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8038         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
8039
8040         switch (r->in.level) {
8041         case 1:
8042                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
8043                                                    get_session_info_system(),
8044                                                    p->msg_ctx,
8045                                                    r->out.count,
8046                                                    r->out.info);
8047                 break;
8048         default:
8049                 result = WERR_INVALID_LEVEL;
8050                 break;
8051         }
8052
8053         if (!W_ERROR_IS_OK(result)) {
8054                 return result;
8055         }
8056
8057         if (*r->out.count == 0) {
8058                 return WERR_NO_MORE_ITEMS;
8059         }
8060
8061         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8062                                                      spoolss_EnumForms,
8063                                                      *r->out.info, r->in.level,
8064                                                      *r->out.count);
8065         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8066         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8067
8068         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8069 }
8070
8071 /****************************************************************
8072  _spoolss_GetForm
8073 ****************************************************************/
8074
8075 WERROR _spoolss_GetForm(struct pipes_struct *p,
8076                         struct spoolss_GetForm *r)
8077 {
8078         WERROR result;
8079
8080         /* that's an [in out] buffer */
8081
8082         if (!r->in.buffer && (r->in.offered != 0)) {
8083                 TALLOC_FREE(r->out.info);
8084                 return WERR_INVALID_PARAMETER;
8085         }
8086
8087         DEBUG(4,("_spoolss_GetForm\n"));
8088         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8089         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
8090
8091         switch (r->in.level) {
8092         case 1:
8093                 result = winreg_printer_getform1_internal(p->mem_ctx,
8094                                                  get_session_info_system(),
8095                                                  p->msg_ctx,
8096                                                  r->in.form_name,
8097                                                  &r->out.info->info1);
8098                 break;
8099         default:
8100                 result = WERR_INVALID_LEVEL;
8101                 break;
8102         }
8103
8104         if (!W_ERROR_IS_OK(result)) {
8105                 TALLOC_FREE(r->out.info);
8106                 return result;
8107         }
8108
8109         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
8110                                                r->out.info, r->in.level);
8111         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8112
8113         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8114 }
8115
8116 /****************************************************************************
8117 ****************************************************************************/
8118
8119 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
8120                           struct spoolss_PortInfo1 *r,
8121                           const char *name)
8122 {
8123         r->port_name = talloc_strdup(mem_ctx, name);
8124         W_ERROR_HAVE_NO_MEMORY(r->port_name);
8125
8126         return WERR_OK;
8127 }
8128
8129 /****************************************************************************
8130  TODO: This probably needs distinguish between TCP/IP and Local ports
8131  somehow.
8132 ****************************************************************************/
8133
8134 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
8135                           struct spoolss_PortInfo2 *r,
8136                           const char *name)
8137 {
8138         r->port_name = talloc_strdup(mem_ctx, name);
8139         W_ERROR_HAVE_NO_MEMORY(r->port_name);
8140
8141         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
8142         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8143
8144         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
8145         W_ERROR_HAVE_NO_MEMORY(r->description);
8146
8147         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
8148         r->reserved = 0;
8149
8150         return WERR_OK;
8151 }
8152
8153
8154 /****************************************************************************
8155  wrapper around the enumer ports command
8156 ****************************************************************************/
8157
8158 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
8159 {
8160         char *cmd = lp_enumports_command(talloc_tos());
8161         char **qlines = NULL;
8162         char *command = NULL;
8163         int numlines;
8164         int ret;
8165         int fd;
8166
8167         *count = 0;
8168         *lines = NULL;
8169
8170         /* if no hook then just fill in the default port */
8171
8172         if ( !*cmd ) {
8173                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
8174                         return WERR_NOT_ENOUGH_MEMORY;
8175                 }
8176                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
8177                         TALLOC_FREE(qlines);
8178                         return WERR_NOT_ENOUGH_MEMORY;
8179                 }
8180                 qlines[1] = NULL;
8181                 numlines = 1;
8182         }
8183         else {
8184                 /* we have a valid enumport command */
8185
8186                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
8187                 if (!command) {
8188                         return WERR_NOT_ENOUGH_MEMORY;
8189                 }
8190
8191                 DEBUG(10,("Running [%s]\n", command));
8192                 ret = smbrun(command, &fd, NULL);
8193                 DEBUG(10,("Returned [%d]\n", ret));
8194                 TALLOC_FREE(command);
8195                 if (ret != 0) {
8196                         if (fd != -1) {
8197                                 close(fd);
8198                         }
8199                         return WERR_ACCESS_DENIED;
8200                 }
8201
8202                 numlines = 0;
8203                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
8204                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8205                 close(fd);
8206         }
8207
8208         *count = numlines;
8209         *lines = qlines;
8210
8211         return WERR_OK;
8212 }
8213
8214 /****************************************************************************
8215  enumports level 1.
8216 ****************************************************************************/
8217
8218 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8219                                 union spoolss_PortInfo **info_p,
8220                                 uint32_t *count)
8221 {
8222         union spoolss_PortInfo *info = NULL;
8223         int i=0;
8224         WERROR result = WERR_OK;
8225         char **qlines = NULL;
8226         int numlines = 0;
8227
8228         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8229         if (!W_ERROR_IS_OK(result)) {
8230                 goto out;
8231         }
8232
8233         if (numlines) {
8234                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8235                 if (!info) {
8236                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8237                         result = WERR_NOT_ENOUGH_MEMORY;
8238                         goto out;
8239                 }
8240
8241                 for (i=0; i<numlines; i++) {
8242                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8243                         result = fill_port_1(info, &info[i].info1, qlines[i]);
8244                         if (!W_ERROR_IS_OK(result)) {
8245                                 goto out;
8246                         }
8247                 }
8248         }
8249         TALLOC_FREE(qlines);
8250
8251 out:
8252         if (!W_ERROR_IS_OK(result)) {
8253                 TALLOC_FREE(info);
8254                 TALLOC_FREE(qlines);
8255                 *count = 0;
8256                 *info_p = NULL;
8257                 return result;
8258         }
8259
8260         *info_p = info;
8261         *count = numlines;
8262
8263         return WERR_OK;
8264 }
8265
8266 /****************************************************************************
8267  enumports level 2.
8268 ****************************************************************************/
8269
8270 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8271                                 union spoolss_PortInfo **info_p,
8272                                 uint32_t *count)
8273 {
8274         union spoolss_PortInfo *info = NULL;
8275         int i=0;
8276         WERROR result = WERR_OK;
8277         char **qlines = NULL;
8278         int numlines = 0;
8279
8280         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8281         if (!W_ERROR_IS_OK(result)) {
8282                 goto out;
8283         }
8284
8285         if (numlines) {
8286                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8287                 if (!info) {
8288                         DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8289                         result = WERR_NOT_ENOUGH_MEMORY;
8290                         goto out;
8291                 }
8292
8293                 for (i=0; i<numlines; i++) {
8294                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8295                         result = fill_port_2(info, &info[i].info2, qlines[i]);
8296                         if (!W_ERROR_IS_OK(result)) {
8297                                 goto out;
8298                         }
8299                 }
8300         }
8301         TALLOC_FREE(qlines);
8302
8303 out:
8304         if (!W_ERROR_IS_OK(result)) {
8305                 TALLOC_FREE(info);
8306                 TALLOC_FREE(qlines);
8307                 *count = 0;
8308                 *info_p = NULL;
8309                 return result;
8310         }
8311
8312         *info_p = info;
8313         *count = numlines;
8314
8315         return WERR_OK;
8316 }
8317
8318 /****************************************************************
8319  _spoolss_EnumPorts
8320 ****************************************************************/
8321
8322 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8323                           struct spoolss_EnumPorts *r)
8324 {
8325         WERROR result;
8326
8327         /* that's an [in out] buffer */
8328
8329         if (!r->in.buffer && (r->in.offered != 0)) {
8330                 return WERR_INVALID_PARAMETER;
8331         }
8332
8333         DEBUG(4,("_spoolss_EnumPorts\n"));
8334
8335         *r->out.count = 0;
8336         *r->out.needed = 0;
8337         *r->out.info = NULL;
8338
8339         switch (r->in.level) {
8340         case 1:
8341                 result = enumports_level_1(p->mem_ctx, r->out.info,
8342                                            r->out.count);
8343                 break;
8344         case 2:
8345                 result = enumports_level_2(p->mem_ctx, r->out.info,
8346                                            r->out.count);
8347                 break;
8348         default:
8349                 return WERR_INVALID_LEVEL;
8350         }
8351
8352         if (!W_ERROR_IS_OK(result)) {
8353                 return result;
8354         }
8355
8356         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8357                                                      spoolss_EnumPorts,
8358                                                      *r->out.info, r->in.level,
8359                                                      *r->out.count);
8360         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8361         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8362
8363         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8364 }
8365
8366 /****************************************************************************
8367 ****************************************************************************/
8368
8369 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8370                                            const char *server,
8371                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8372                                            struct spoolss_DeviceMode *devmode,
8373                                            struct security_descriptor *secdesc,
8374                                            struct spoolss_UserLevelCtr *user_ctr,
8375                                            struct policy_handle *handle)
8376 {
8377         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8378         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8379         int     snum;
8380         WERROR err = WERR_OK;
8381
8382         /* samba does not have a concept of local, non-shared printers yet, so
8383          * make sure we always setup sharename - gd */
8384         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8385             (info2->printername != NULL && info2->printername[0] != '\0')) {
8386                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8387                         "no sharename has been set, setting printername %s as sharename\n",
8388                         info2->printername));
8389                 info2->sharename = info2->printername;
8390         }
8391
8392         /* check to see if the printer already exists */
8393         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8394                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8395                         info2->sharename));
8396                 return WERR_PRINTER_ALREADY_EXISTS;
8397         }
8398
8399         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8400                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8401                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8402                                 info2->printername));
8403                         return WERR_PRINTER_ALREADY_EXISTS;
8404                 }
8405         }
8406
8407         /* validate printer info struct */
8408         if (!info2->printername || strlen(info2->printername) == 0) {
8409                 return WERR_INVALID_PRINTER_NAME;
8410         }
8411         if (!info2->portname || strlen(info2->portname) == 0) {
8412                 return WERR_UNKNOWN_PORT;
8413         }
8414         if (!info2->drivername || strlen(info2->drivername) == 0) {
8415                 return WERR_UNKNOWN_PRINTER_DRIVER;
8416         }
8417         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8418                 return WERR_UNKNOWN_PRINTPROCESSOR;
8419         }
8420
8421         /* FIXME!!!  smbd should check to see if the driver is installed before
8422            trying to add a printer like this  --jerry */
8423
8424         if (*lp_addprinter_command(talloc_tos()) ) {
8425                 char *raddr;
8426
8427                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8428                                                          p->mem_ctx);
8429                 if (raddr == NULL) {
8430                         return WERR_NOT_ENOUGH_MEMORY;
8431                 }
8432
8433                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8434                                        info2, raddr,
8435                                        p->msg_ctx) ) {
8436                         return WERR_ACCESS_DENIED;
8437                 }
8438         } else {
8439                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8440                         "smb.conf parameter \"addprinter command\" is defined. This "
8441                         "parameter must exist for this call to succeed\n",
8442                         info2->sharename ));
8443         }
8444
8445         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8446                 return WERR_ACCESS_DENIED;
8447         }
8448
8449         /* you must be a printer admin to add a new printer */
8450         if (!W_ERROR_IS_OK(print_access_check(p->session_info,
8451                                               p->msg_ctx,
8452                                               snum,
8453                                               PRINTER_ACCESS_ADMINISTER))) {
8454                 return WERR_ACCESS_DENIED;
8455         }
8456
8457         /*
8458          * Do sanity check on the requested changes for Samba.
8459          */
8460
8461         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8462                 return WERR_INVALID_PARAMETER;
8463         }
8464
8465         if (devmode == NULL) {
8466                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8467         }
8468
8469         err = update_dsspooler(p->mem_ctx,
8470                                get_session_info_system(),
8471                                p->msg_ctx,
8472                                0,
8473                                info2,
8474                                NULL);
8475         if (!W_ERROR_IS_OK(err)) {
8476                 return err;
8477         }
8478
8479         err = winreg_update_printer_internal(p->mem_ctx,
8480                                     get_session_info_system(),
8481                                     p->msg_ctx,
8482                                     info2->sharename,
8483                                     info2_mask,
8484                                     info2,
8485                                     devmode,
8486                                     secdesc);
8487         if (!W_ERROR_IS_OK(err)) {
8488                 return err;
8489         }
8490
8491         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8492         if (!W_ERROR_IS_OK(err)) {
8493                 /* Handle open failed - remove addition. */
8494                 ZERO_STRUCTP(handle);
8495                 return err;
8496         }
8497
8498         return WERR_OK;
8499 }
8500
8501 /****************************************************************
8502  _spoolss_AddPrinterEx
8503 ****************************************************************/
8504
8505 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8506                              struct spoolss_AddPrinterEx *r)
8507 {
8508         switch (r->in.info_ctr->level) {
8509         case 1:
8510                 /* we don't handle yet */
8511                 /* but I know what to do ... */
8512                 return WERR_INVALID_LEVEL;
8513         case 2:
8514                 return spoolss_addprinterex_level_2(p, r->in.server,
8515                                                     r->in.info_ctr,
8516                                                     r->in.devmode_ctr->devmode,
8517                                                     r->in.secdesc_ctr->sd,
8518                                                     r->in.userlevel_ctr,
8519                                                     r->out.handle);
8520         default:
8521                 return WERR_INVALID_LEVEL;
8522         }
8523 }
8524
8525 /****************************************************************
8526  _spoolss_AddPrinter
8527 ****************************************************************/
8528
8529 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8530                            struct spoolss_AddPrinter *r)
8531 {
8532         struct spoolss_AddPrinterEx a;
8533         struct spoolss_UserLevelCtr userlevel_ctr;
8534
8535         ZERO_STRUCT(userlevel_ctr);
8536
8537         userlevel_ctr.level = 1;
8538
8539         a.in.server             = r->in.server;
8540         a.in.info_ctr           = r->in.info_ctr;
8541         a.in.devmode_ctr        = r->in.devmode_ctr;
8542         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8543         a.in.userlevel_ctr      = &userlevel_ctr;
8544         a.out.handle            = r->out.handle;
8545
8546         return _spoolss_AddPrinterEx(p, &a);
8547 }
8548
8549 /****************************************************************
8550  _spoolss_AddPrinterDriverEx
8551 ****************************************************************/
8552
8553 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8554                                    struct spoolss_AddPrinterDriverEx *r)
8555 {
8556         WERROR err = WERR_OK;
8557         const char *driver_name = NULL;
8558         const char *driver_directory = NULL;
8559         uint32_t version;
8560
8561         /*
8562          * we only support the semantics of AddPrinterDriver()
8563          * i.e. only copy files that are newer than existing ones
8564          */
8565
8566         if (r->in.flags == 0) {
8567                 return WERR_INVALID_PARAMETER;
8568         }
8569
8570         if (!(r->in.flags & APD_COPY_ALL_FILES) &&
8571             !(r->in.flags & APD_COPY_NEW_FILES)) {
8572                 return WERR_ACCESS_DENIED;
8573         }
8574
8575         /* FIXME */
8576         if (r->in.info_ctr->level != 3 &&
8577             r->in.info_ctr->level != 6 &&
8578             r->in.info_ctr->level != 8) {
8579                 DEBUG(0,("%s: level %d not yet implemented\n", __func__,
8580                         r->in.info_ctr->level));
8581                 return WERR_INVALID_LEVEL;
8582         }
8583
8584         DEBUG(5,("Cleaning driver's information\n"));
8585         err = clean_up_driver_struct(p->mem_ctx,
8586                                      p->session_info,
8587                                      r->in.info_ctr,
8588                                      r->in.flags,
8589                                      &driver_directory);
8590         if (!W_ERROR_IS_OK(err)) {
8591                 DBG_ERR("clean_up_driver_struct failed - %s\n",
8592                         win_errstr(err));
8593                 goto done;
8594         }
8595
8596         DEBUG(5,("Moving driver to final destination\n"));
8597         err = move_driver_to_download_area(p->session_info,
8598                                            r->in.info_ctr,
8599                                            driver_directory);
8600         if (!W_ERROR_IS_OK(err)) {
8601                 DBG_ERR("move_driver_to_download_area failed - %s\n",
8602                         win_errstr(err));
8603                 goto done;
8604         }
8605
8606         err = winreg_add_driver_internal(p->mem_ctx,
8607                                 get_session_info_system(),
8608                                 p->msg_ctx,
8609                                 r->in.info_ctr,
8610                                 &driver_name,
8611                                 &version);
8612         if (!W_ERROR_IS_OK(err)) {
8613                 DBG_ERR("winreg_add_driver_internal failed - %s\n",
8614                         win_errstr(err));
8615                 goto done;
8616         }
8617
8618         /*
8619          * I think this is where he DrvUpgradePrinter() hook would be
8620          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8621          * server.  Right now, we just need to send ourselves a message
8622          * to update each printer bound to this driver.   --jerry
8623          */
8624
8625         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8626                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8627                         __func__, driver_name));
8628         }
8629
8630 done:
8631         return err;
8632 }
8633
8634 /****************************************************************
8635  _spoolss_AddPrinterDriver
8636 ****************************************************************/
8637
8638 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8639                                  struct spoolss_AddPrinterDriver *r)
8640 {
8641         struct spoolss_AddPrinterDriverEx a;
8642
8643         switch (r->in.info_ctr->level) {
8644         case 2:
8645         case 3:
8646         case 4:
8647         case 5:
8648                 break;
8649         default:
8650                 return WERR_INVALID_LEVEL;
8651         }
8652
8653         a.in.servername         = r->in.servername;
8654         a.in.info_ctr           = r->in.info_ctr;
8655         a.in.flags              = APD_COPY_NEW_FILES;
8656
8657         return _spoolss_AddPrinterDriverEx(p, &a);
8658 }
8659
8660 /****************************************************************************
8661 ****************************************************************************/
8662
8663 struct _spoolss_paths {
8664         int type;
8665         const char *share;
8666         const char *dir;
8667 };
8668
8669 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8670
8671 static const struct _spoolss_paths spoolss_paths[]= {
8672         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8673         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8674 };
8675
8676 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8677                                           const char *servername,
8678                                           const char *environment,
8679                                           int component,
8680                                           char **path)
8681 {
8682         const char *pservername = NULL;
8683         const char *long_archi;
8684         const char *short_archi;
8685
8686         *path = NULL;
8687
8688         /* environment may be empty */
8689         if (environment && strlen(environment)) {
8690                 long_archi = environment;
8691         } else {
8692                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8693                                                   "spoolss", "architecture",
8694                                                   GLOBAL_SPOOLSS_ARCHITECTURE);
8695         }
8696
8697         /* servername may be empty */
8698         if (servername && strlen(servername)) {
8699                 pservername = canon_servername(servername);
8700
8701                 if (!is_myname_or_ipaddr(pservername)) {
8702                         return WERR_INVALID_PARAMETER;
8703                 }
8704         }
8705
8706         if (!(short_archi = get_short_archi(long_archi))) {
8707                 return WERR_INVALID_ENVIRONMENT;
8708         }
8709
8710         switch (component) {
8711         case SPOOLSS_PRTPROCS_PATH:
8712         case SPOOLSS_DRIVER_PATH:
8713                 if (pservername) {
8714                         *path = talloc_asprintf(mem_ctx,
8715                                         "\\\\%s\\%s\\%s",
8716                                         pservername,
8717                                         spoolss_paths[component].share,
8718                                         short_archi);
8719                 } else {
8720                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8721                                         SPOOLSS_DEFAULT_SERVER_PATH,
8722                                         spoolss_paths[component].dir,
8723                                         short_archi);
8724                 }
8725                 break;
8726         default:
8727                 return WERR_INVALID_PARAMETER;
8728         }
8729
8730         if (!*path) {
8731                 return WERR_NOT_ENOUGH_MEMORY;
8732         }
8733
8734         return WERR_OK;
8735 }
8736
8737 /****************************************************************************
8738 ****************************************************************************/
8739
8740 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8741                                           const char *servername,
8742                                           const char *environment,
8743                                           struct spoolss_DriverDirectoryInfo1 *r)
8744 {
8745         WERROR werr;
8746         char *path = NULL;
8747
8748         werr = compose_spoolss_server_path(mem_ctx,
8749                                            servername,
8750                                            environment,
8751                                            SPOOLSS_DRIVER_PATH,
8752                                            &path);
8753         if (!W_ERROR_IS_OK(werr)) {
8754                 return werr;
8755         }
8756
8757         DEBUG(4,("printer driver directory: [%s]\n", path));
8758
8759         r->directory_name = path;
8760
8761         return WERR_OK;
8762 }
8763
8764 /****************************************************************
8765  _spoolss_GetPrinterDriverDirectory
8766 ****************************************************************/
8767
8768 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8769                                           struct spoolss_GetPrinterDriverDirectory *r)
8770 {
8771         WERROR werror;
8772
8773         /* that's an [in out] buffer */
8774
8775         if (!r->in.buffer && (r->in.offered != 0)) {
8776                 TALLOC_FREE(r->out.info);
8777                 return WERR_INVALID_PARAMETER;
8778         }
8779
8780         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8781                 r->in.level));
8782
8783         *r->out.needed = 0;
8784
8785         /* r->in.level is ignored */
8786
8787         werror = getprinterdriverdir_level_1(p->mem_ctx,
8788                                              r->in.server,
8789                                              r->in.environment,
8790                                              &r->out.info->info1);
8791         if (!W_ERROR_IS_OK(werror)) {
8792                 TALLOC_FREE(r->out.info);
8793                 return werror;
8794         }
8795
8796         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8797                                                r->out.info, r->in.level);
8798         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8799
8800         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8801 }
8802
8803 /****************************************************************
8804  _spoolss_EnumPrinterData
8805 ****************************************************************/
8806
8807 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8808                                 struct spoolss_EnumPrinterData *r)
8809 {
8810         WERROR result;
8811         struct spoolss_EnumPrinterDataEx r2;
8812         uint32_t count;
8813         struct spoolss_PrinterEnumValues *info, *val = NULL;
8814         uint32_t needed;
8815
8816         r2.in.handle    = r->in.handle;
8817         r2.in.key_name  = "PrinterDriverData";
8818         r2.in.offered   = 0;
8819         r2.out.count    = &count;
8820         r2.out.info     = &info;
8821         r2.out.needed   = &needed;
8822
8823         result = _spoolss_EnumPrinterDataEx(p, &r2);
8824         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8825                 r2.in.offered = needed;
8826                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8827         }
8828         if (!W_ERROR_IS_OK(result)) {
8829                 return result;
8830         }
8831
8832         /*
8833          * The NT machine wants to know the biggest size of value and data
8834          *
8835          * cf: MSDN EnumPrinterData remark section
8836          */
8837
8838         if (!r->in.value_offered && !r->in.data_offered) {
8839                 uint32_t biggest_valuesize = 0;
8840                 uint32_t biggest_datasize = 0;
8841                 int i, name_length;
8842
8843                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8844
8845                 for (i=0; i<count; i++) {
8846
8847                         name_length = strlen(info[i].value_name);
8848                         if (strlen(info[i].value_name) > biggest_valuesize) {
8849                                 biggest_valuesize = name_length;
8850                         }
8851
8852                         if (info[i].data_length > biggest_datasize) {
8853                                 biggest_datasize = info[i].data_length;
8854                         }
8855
8856                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8857                                 biggest_datasize));
8858                 }
8859
8860                 /* the value is an UNICODE string but real_value_size is the length
8861                    in bytes including the trailing 0 */
8862
8863                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8864                 *r->out.data_needed  = biggest_datasize;
8865
8866                 DEBUG(6,("final values: [%d], [%d]\n",
8867                         *r->out.value_needed, *r->out.data_needed));
8868
8869                 return WERR_OK;
8870         }
8871
8872         if (r->in.enum_index < count) {
8873                 val = &info[r->in.enum_index];
8874         }
8875
8876         if (val == NULL) {
8877                 /* out_value should default to "" or else NT4 has
8878                    problems unmarshalling the response */
8879
8880                 if (r->in.value_offered) {
8881                         *r->out.value_needed = 1;
8882                         r->out.value_name = talloc_strdup(r, "");
8883                         if (!r->out.value_name) {
8884                                 return WERR_NOT_ENOUGH_MEMORY;
8885                         }
8886                 } else {
8887                         r->out.value_name = NULL;
8888                         *r->out.value_needed = 0;
8889                 }
8890
8891                 /* the data is counted in bytes */
8892
8893                 *r->out.data_needed = r->in.data_offered;
8894
8895                 result = WERR_NO_MORE_ITEMS;
8896         } else {
8897                 /*
8898                  * the value is:
8899                  * - counted in bytes in the request
8900                  * - counted in UNICODE chars in the max reply
8901                  * - counted in bytes in the real size
8902                  *
8903                  * take a pause *before* coding not *during* coding
8904                  */
8905
8906                 /* name */
8907                 if (r->in.value_offered) {
8908                         r->out.value_name = talloc_strdup(r, val->value_name);
8909                         if (!r->out.value_name) {
8910                                 return WERR_NOT_ENOUGH_MEMORY;
8911                         }
8912                         *r->out.value_needed = val->value_name_len;
8913                 } else {
8914                         r->out.value_name = NULL;
8915                         *r->out.value_needed = 0;
8916                 }
8917
8918                 /* type */
8919
8920                 *r->out.type = val->type;
8921
8922                 /* data - counted in bytes */
8923
8924                 /*
8925                  * See the section "Dynamically Typed Query Parameters"
8926                  * in MS-RPRN.
8927                  */
8928
8929                 if (r->out.data && val->data && val->data->data &&
8930                                 val->data_length && r->in.data_offered) {
8931                         memcpy(r->out.data, val->data->data,
8932                                 MIN(val->data_length,r->in.data_offered));
8933                 }
8934
8935                 *r->out.data_needed = val->data_length;
8936
8937                 result = WERR_OK;
8938         }
8939
8940         return result;
8941 }
8942
8943 /****************************************************************
8944  _spoolss_SetPrinterData
8945 ****************************************************************/
8946
8947 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8948                                struct spoolss_SetPrinterData *r)
8949 {
8950         struct spoolss_SetPrinterDataEx r2;
8951
8952         r2.in.handle            = r->in.handle;
8953         r2.in.key_name          = "PrinterDriverData";
8954         r2.in.value_name        = r->in.value_name;
8955         r2.in.type              = r->in.type;
8956         r2.in.data              = r->in.data;
8957         r2.in.offered           = r->in.offered;
8958
8959         return _spoolss_SetPrinterDataEx(p, &r2);
8960 }
8961
8962 /****************************************************************
8963  _spoolss_ResetPrinter
8964 ****************************************************************/
8965
8966 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8967                              struct spoolss_ResetPrinter *r)
8968 {
8969         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8970         int             snum;
8971
8972         DEBUG(5,("_spoolss_ResetPrinter\n"));
8973
8974         /*
8975          * All we do is to check to see if the handle and queue is valid.
8976          * This call really doesn't mean anything to us because we only
8977          * support RAW printing.   --jerry
8978          */
8979
8980         if (!Printer) {
8981                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8982                         OUR_HANDLE(r->in.handle)));
8983                 return WERR_INVALID_HANDLE;
8984         }
8985
8986         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8987                 return WERR_INVALID_HANDLE;
8988
8989
8990         /* blindly return success */
8991         return WERR_OK;
8992 }
8993
8994 /****************************************************************
8995  _spoolss_DeletePrinterData
8996 ****************************************************************/
8997
8998 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8999                                   struct spoolss_DeletePrinterData *r)
9000 {
9001         struct spoolss_DeletePrinterDataEx r2;
9002
9003         r2.in.handle            = r->in.handle;
9004         r2.in.key_name          = "PrinterDriverData";
9005         r2.in.value_name        = r->in.value_name;
9006
9007         return _spoolss_DeletePrinterDataEx(p, &r2);
9008 }
9009
9010 /****************************************************************
9011  _spoolss_AddForm
9012 ****************************************************************/
9013
9014 WERROR _spoolss_AddForm(struct pipes_struct *p,
9015                         struct spoolss_AddForm *r)
9016 {
9017         struct spoolss_AddFormInfo1 *form;
9018         int snum = -1;
9019         WERROR status = WERR_OK;
9020         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9021         struct dcerpc_binding_handle *b;
9022         TALLOC_CTX *tmp_ctx = NULL;
9023
9024         DEBUG(5,("_spoolss_AddForm\n"));
9025
9026         if (!Printer) {
9027                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
9028                         OUR_HANDLE(r->in.handle)));
9029                 return WERR_INVALID_HANDLE;
9030         }
9031
9032         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9033            and not a printer admin, then fail */
9034
9035         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9036             !security_token_has_privilege(p->session_info->security_token,
9037                                           SEC_PRIV_PRINT_OPERATOR)) {
9038                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
9039                 return WERR_ACCESS_DENIED;
9040         }
9041
9042         if (r->in.info_ctr->level != 1) {
9043                 return WERR_INVALID_LEVEL;
9044         }
9045
9046         form = r->in.info_ctr->info.info1;
9047         if (!form) {
9048                 return WERR_INVALID_PARAMETER;
9049         }
9050
9051         switch (form->flags) {
9052         case SPOOLSS_FORM_USER:
9053         case SPOOLSS_FORM_BUILTIN:
9054         case SPOOLSS_FORM_PRINTER:
9055                 break;
9056         default:
9057                 return WERR_INVALID_PARAMETER;
9058         }
9059
9060         tmp_ctx = talloc_new(p->mem_ctx);
9061         if (!tmp_ctx) {
9062                 return WERR_NOT_ENOUGH_MEMORY;
9063         }
9064
9065         status = winreg_printer_binding_handle(tmp_ctx,
9066                                                get_session_info_system(),
9067                                                p->msg_ctx,
9068                                                &b);
9069         if (!W_ERROR_IS_OK(status)) {
9070                 goto done;
9071         }
9072
9073         status = winreg_printer_addform1(tmp_ctx, b, form);
9074         if (!W_ERROR_IS_OK(status)) {
9075                 goto done;
9076         }
9077
9078         /*
9079          * ChangeID must always be set if this is a printer
9080          */
9081         if (Printer->printer_type == SPLHND_PRINTER) {
9082                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9083                         status = WERR_INVALID_HANDLE;
9084                         goto done;
9085                 }
9086
9087                 status = winreg_printer_update_changeid(tmp_ctx, b,
9088                                                         lp_const_servicename(snum));
9089         }
9090
9091 done:
9092         talloc_free(tmp_ctx);
9093         return status;
9094 }
9095
9096 /****************************************************************
9097  _spoolss_DeleteForm
9098 ****************************************************************/
9099
9100 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
9101                            struct spoolss_DeleteForm *r)
9102 {
9103         const char *form_name = r->in.form_name;
9104         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9105         int snum = -1;
9106         WERROR status = WERR_OK;
9107         struct dcerpc_binding_handle *b;
9108         TALLOC_CTX *tmp_ctx = NULL;
9109
9110         DEBUG(5,("_spoolss_DeleteForm\n"));
9111
9112         if (!Printer) {
9113                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
9114                         OUR_HANDLE(r->in.handle)));
9115                 return WERR_INVALID_HANDLE;
9116         }
9117
9118         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9119             !security_token_has_privilege(p->session_info->security_token,
9120                                           SEC_PRIV_PRINT_OPERATOR)) {
9121                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
9122                 return WERR_ACCESS_DENIED;
9123         }
9124
9125         tmp_ctx = talloc_new(p->mem_ctx);
9126         if (!tmp_ctx) {
9127                 return WERR_NOT_ENOUGH_MEMORY;
9128         }
9129
9130         status = winreg_printer_binding_handle(tmp_ctx,
9131                                                get_session_info_system(),
9132                                                p->msg_ctx,
9133                                                &b);
9134         if (!W_ERROR_IS_OK(status)) {
9135                 goto done;
9136         }
9137
9138         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
9139         if (!W_ERROR_IS_OK(status)) {
9140                 goto done;
9141         }
9142
9143         /*
9144          * ChangeID must always be set if this is a printer
9145          */
9146         if (Printer->printer_type == SPLHND_PRINTER) {
9147                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9148                         status = WERR_INVALID_HANDLE;
9149                         goto done;
9150                 }
9151
9152                 status = winreg_printer_update_changeid(tmp_ctx, b,
9153                                                         lp_const_servicename(snum));
9154         }
9155
9156 done:
9157         talloc_free(tmp_ctx);
9158         return status;
9159 }
9160
9161 /****************************************************************
9162  _spoolss_SetForm
9163 ****************************************************************/
9164
9165 WERROR _spoolss_SetForm(struct pipes_struct *p,
9166                         struct spoolss_SetForm *r)
9167 {
9168         struct spoolss_AddFormInfo1 *form;
9169         const char *form_name = r->in.form_name;
9170         int snum = -1;
9171         WERROR status = WERR_OK;
9172         struct dcerpc_binding_handle *b;
9173         TALLOC_CTX *tmp_ctx = NULL;
9174
9175         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9176
9177         DEBUG(5,("_spoolss_SetForm\n"));
9178
9179         if (!Printer) {
9180                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
9181                         OUR_HANDLE(r->in.handle)));
9182                 return WERR_INVALID_HANDLE;
9183         }
9184
9185         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9186            and not a printer admin, then fail */
9187
9188         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9189              !security_token_has_privilege(p->session_info->security_token,
9190                                            SEC_PRIV_PRINT_OPERATOR)) {
9191                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
9192                 return WERR_ACCESS_DENIED;
9193         }
9194
9195         if (r->in.info_ctr->level != 1) {
9196                 return WERR_INVALID_LEVEL;
9197         }
9198
9199         form = r->in.info_ctr->info.info1;
9200         if (!form) {
9201                 return WERR_INVALID_PARAMETER;
9202         }
9203
9204         tmp_ctx = talloc_new(p->mem_ctx);
9205         if (!tmp_ctx) {
9206                 return WERR_NOT_ENOUGH_MEMORY;
9207         }
9208
9209         status = winreg_printer_binding_handle(tmp_ctx,
9210                                                get_session_info_system(),
9211                                                p->msg_ctx,
9212                                                &b);
9213         if (!W_ERROR_IS_OK(status)) {
9214                 goto done;
9215         }
9216
9217         status = winreg_printer_setform1(tmp_ctx, b,
9218                                          form_name,
9219                                          form);
9220         if (!W_ERROR_IS_OK(status)) {
9221                 goto done;
9222         }
9223
9224         /*
9225          * ChangeID must always be set if this is a printer
9226          */
9227         if (Printer->printer_type == SPLHND_PRINTER) {
9228                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9229                         status = WERR_INVALID_HANDLE;
9230                         goto done;
9231                 }
9232
9233                 status = winreg_printer_update_changeid(tmp_ctx, b,
9234                                                         lp_const_servicename(snum));
9235         }
9236
9237 done:
9238         talloc_free(tmp_ctx);
9239         return status;
9240 }
9241
9242 /****************************************************************************
9243  fill_print_processor1
9244 ****************************************************************************/
9245
9246 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9247                                     struct spoolss_PrintProcessorInfo1 *r,
9248                                     const char *print_processor_name)
9249 {
9250         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9251         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9252
9253         return WERR_OK;
9254 }
9255
9256 /****************************************************************************
9257  enumprintprocessors level 1.
9258 ****************************************************************************/
9259
9260 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9261                                           union spoolss_PrintProcessorInfo **info_p,
9262                                           uint32_t *count)
9263 {
9264         union spoolss_PrintProcessorInfo *info;
9265         WERROR result;
9266
9267         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9268         W_ERROR_HAVE_NO_MEMORY(info);
9269
9270         *count = 1;
9271
9272         result = fill_print_processor1(info, &info[0].info1, "winprint");
9273         if (!W_ERROR_IS_OK(result)) {
9274                 goto out;
9275         }
9276
9277  out:
9278         if (!W_ERROR_IS_OK(result)) {
9279                 TALLOC_FREE(info);
9280                 *count = 0;
9281                 return result;
9282         }
9283
9284         *info_p = info;
9285
9286         return WERR_OK;
9287 }
9288
9289 /****************************************************************
9290  _spoolss_EnumPrintProcessors
9291 ****************************************************************/
9292
9293 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9294                                     struct spoolss_EnumPrintProcessors *r)
9295 {
9296         WERROR result;
9297
9298         /* that's an [in out] buffer */
9299
9300         if (!r->in.buffer && (r->in.offered != 0)) {
9301                 return WERR_INVALID_PARAMETER;
9302         }
9303
9304         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9305
9306         /*
9307          * Enumerate the print processors ...
9308          *
9309          * Just reply with "winprint", to keep NT happy
9310          * and I can use my nice printer checker.
9311          */
9312
9313         *r->out.count = 0;
9314         *r->out.needed = 0;
9315         *r->out.info = NULL;
9316
9317         if (!get_short_archi(r->in.environment)) {
9318                 return WERR_INVALID_ENVIRONMENT;
9319         }
9320
9321         switch (r->in.level) {
9322         case 1:
9323                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9324                                                      r->out.count);
9325                 break;
9326         default:
9327                 return WERR_INVALID_LEVEL;
9328         }
9329
9330         if (!W_ERROR_IS_OK(result)) {
9331                 return result;
9332         }
9333
9334         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9335                                                      spoolss_EnumPrintProcessors,
9336                                                      *r->out.info, r->in.level,
9337                                                      *r->out.count);
9338         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9339         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9340
9341         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9342 }
9343
9344 /****************************************************************************
9345  fill_printprocdatatype1
9346 ****************************************************************************/
9347
9348 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9349                                       struct spoolss_PrintProcDataTypesInfo1 *r,
9350                                       const char *name_array)
9351 {
9352         r->name_array = talloc_strdup(mem_ctx, name_array);
9353         W_ERROR_HAVE_NO_MEMORY(r->name_array);
9354
9355         return WERR_OK;
9356 }
9357
9358 /****************************************************************************
9359  enumprintprocdatatypes level 1.
9360 ****************************************************************************/
9361
9362 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9363                                              union spoolss_PrintProcDataTypesInfo **info_p,
9364                                              uint32_t *count)
9365 {
9366         WERROR result;
9367         union spoolss_PrintProcDataTypesInfo *info;
9368
9369         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9370         W_ERROR_HAVE_NO_MEMORY(info);
9371
9372         *count = 1;
9373
9374         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9375         if (!W_ERROR_IS_OK(result)) {
9376                 goto out;
9377         }
9378
9379  out:
9380         if (!W_ERROR_IS_OK(result)) {
9381                 TALLOC_FREE(info);
9382                 *count = 0;
9383                 return result;
9384         }
9385
9386         *info_p = info;
9387
9388         return WERR_OK;
9389 }
9390
9391 /****************************************************************
9392  _spoolss_EnumPrintProcessorDataTypes
9393 ****************************************************************/
9394
9395 WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
9396                                             struct spoolss_EnumPrintProcessorDataTypes *r)
9397 {
9398         WERROR result;
9399
9400         /* that's an [in out] buffer */
9401
9402         if (!r->in.buffer && (r->in.offered != 0)) {
9403                 return WERR_INVALID_PARAMETER;
9404         }
9405
9406         DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
9407
9408         *r->out.count = 0;
9409         *r->out.needed = 0;
9410         *r->out.info = NULL;
9411
9412         if (r->in.print_processor_name == NULL ||
9413             !strequal(r->in.print_processor_name, "winprint")) {
9414                 return WERR_UNKNOWN_PRINTPROCESSOR;
9415         }
9416
9417         switch (r->in.level) {
9418         case 1:
9419                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9420                                                         r->out.count);
9421                 break;
9422         default:
9423                 return WERR_INVALID_LEVEL;
9424         }
9425
9426         if (!W_ERROR_IS_OK(result)) {
9427                 return result;
9428         }
9429
9430         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9431                                                      spoolss_EnumPrintProcessorDataTypes,
9432                                                      *r->out.info, r->in.level,
9433                                                      *r->out.count);
9434         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9435         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9436
9437         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9438 }
9439
9440 /****************************************************************************
9441  fill_monitor_1
9442 ****************************************************************************/
9443
9444 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9445                              struct spoolss_MonitorInfo1 *r,
9446                              const char *monitor_name)
9447 {
9448         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9449         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9450
9451         return WERR_OK;
9452 }
9453
9454 /****************************************************************************
9455  fill_monitor_2
9456 ****************************************************************************/
9457
9458 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9459                              struct spoolss_MonitorInfo2 *r,
9460                              const char *monitor_name,
9461                              const char *environment,
9462                              const char *dll_name)
9463 {
9464         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9465         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9466         r->environment                  = talloc_strdup(mem_ctx, environment);
9467         W_ERROR_HAVE_NO_MEMORY(r->environment);
9468         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9469         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9470
9471         return WERR_OK;
9472 }
9473
9474 /****************************************************************************
9475  enumprintmonitors level 1.
9476 ****************************************************************************/
9477
9478 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9479                                         union spoolss_MonitorInfo **info_p,
9480                                         uint32_t *count)
9481 {
9482         union spoolss_MonitorInfo *info;
9483         WERROR result = WERR_OK;
9484
9485         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9486         W_ERROR_HAVE_NO_MEMORY(info);
9487
9488         *count = 2;
9489
9490         result = fill_monitor_1(info, &info[0].info1,
9491                                 SPL_LOCAL_PORT);
9492         if (!W_ERROR_IS_OK(result)) {
9493                 goto out;
9494         }
9495
9496         result = fill_monitor_1(info, &info[1].info1,
9497                                 SPL_TCPIP_PORT);
9498         if (!W_ERROR_IS_OK(result)) {
9499                 goto out;
9500         }
9501
9502 out:
9503         if (!W_ERROR_IS_OK(result)) {
9504                 TALLOC_FREE(info);
9505                 *count = 0;
9506                 return result;
9507         }
9508
9509         *info_p = info;
9510
9511         return WERR_OK;
9512 }
9513
9514 /****************************************************************************
9515  enumprintmonitors level 2.
9516 ****************************************************************************/
9517
9518 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9519                                         union spoolss_MonitorInfo **info_p,
9520                                         uint32_t *count)
9521 {
9522         union spoolss_MonitorInfo *info;
9523         WERROR result = WERR_OK;
9524         const char *architecture;
9525
9526         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9527         W_ERROR_HAVE_NO_MEMORY(info);
9528
9529         *count = 2;
9530
9531         architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
9532                                             "spoolss",
9533                                             "architecture",
9534                                             GLOBAL_SPOOLSS_ARCHITECTURE);
9535
9536         result = fill_monitor_2(info, &info[0].info2,
9537                                 SPL_LOCAL_PORT,
9538                                 architecture,
9539                                 "localmon.dll");
9540         if (!W_ERROR_IS_OK(result)) {
9541                 goto out;
9542         }
9543
9544         result = fill_monitor_2(info, &info[1].info2,
9545                                 SPL_TCPIP_PORT,
9546                                 architecture,
9547                                 "tcpmon.dll");
9548         if (!W_ERROR_IS_OK(result)) {
9549                 goto out;
9550         }
9551
9552 out:
9553         if (!W_ERROR_IS_OK(result)) {
9554                 TALLOC_FREE(info);
9555                 *count = 0;
9556                 return result;
9557         }
9558
9559         *info_p = info;
9560
9561         return WERR_OK;
9562 }
9563
9564 /****************************************************************
9565  _spoolss_EnumMonitors
9566 ****************************************************************/
9567
9568 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9569                              struct spoolss_EnumMonitors *r)
9570 {
9571         WERROR result;
9572
9573         /* that's an [in out] buffer */
9574
9575         if (!r->in.buffer && (r->in.offered != 0)) {
9576                 return WERR_INVALID_PARAMETER;
9577         }
9578
9579         DEBUG(5,("_spoolss_EnumMonitors\n"));
9580
9581         /*
9582          * Enumerate the print monitors ...
9583          *
9584          * Just reply with "Local Port", to keep NT happy
9585          * and I can use my nice printer checker.
9586          */
9587
9588         *r->out.count = 0;
9589         *r->out.needed = 0;
9590         *r->out.info = NULL;
9591
9592         switch (r->in.level) {
9593         case 1:
9594                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9595                                                    r->out.count);
9596                 break;
9597         case 2:
9598                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9599                                                    r->out.count);
9600                 break;
9601         default:
9602                 return WERR_INVALID_LEVEL;
9603         }
9604
9605         if (!W_ERROR_IS_OK(result)) {
9606                 return result;
9607         }
9608
9609         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9610                                                      spoolss_EnumMonitors,
9611                                                      *r->out.info, r->in.level,
9612                                                      *r->out.count);
9613         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9614         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9615
9616         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9617 }
9618
9619 /****************************************************************************
9620 ****************************************************************************/
9621
9622 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9623                              const print_queue_struct *queue,
9624                              int count, int snum,
9625                              struct spoolss_PrinterInfo2 *pinfo2,
9626                              uint32_t jobid,
9627                              int sysjob,
9628                              struct spoolss_JobInfo1 *r)
9629 {
9630         int i = 0;
9631         bool found = false;
9632
9633         for (i=0; i<count; i++) {
9634                 if (queue[i].sysjob == sysjob) {
9635                         found = true;
9636                         break;
9637                 }
9638         }
9639
9640         if (found == false) {
9641                 /* NT treats not found as bad param... yet another bad choice */
9642                 return WERR_INVALID_PARAMETER;
9643         }
9644
9645         return fill_job_info1(mem_ctx,
9646                               r,
9647                               &queue[i],
9648                               jobid,
9649                               i,
9650                               snum,
9651                               pinfo2);
9652 }
9653
9654 /****************************************************************************
9655 ****************************************************************************/
9656
9657 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9658                              const print_queue_struct *queue,
9659                              int count, int snum,
9660                              struct spoolss_PrinterInfo2 *pinfo2,
9661                              uint32_t jobid,
9662                              int sysjob,
9663                              struct spoolss_JobInfo2 *r)
9664 {
9665         int i = 0;
9666         bool found = false;
9667         struct spoolss_DeviceMode *devmode;
9668         WERROR result;
9669
9670         for (i=0; i<count; i++) {
9671                 if (queue[i].sysjob == sysjob) {
9672                         found = true;
9673                         break;
9674                 }
9675         }
9676
9677         if (found == false) {
9678                 /* NT treats not found as bad param... yet another bad
9679                    choice */
9680                 return WERR_INVALID_PARAMETER;
9681         }
9682
9683         /*
9684          * if the print job does not have a DEVMODE associated with it,
9685          * just use the one for the printer. A NULL devicemode is not
9686          *  a failure condition
9687          */
9688
9689         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9690         if (!devmode) {
9691                 result = spoolss_create_default_devmode(mem_ctx,
9692                                                 pinfo2->printername,
9693                                                 &devmode);
9694                 if (!W_ERROR_IS_OK(result)) {
9695                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9696                         return result;
9697                 }
9698         }
9699
9700         return fill_job_info2(mem_ctx,
9701                               r,
9702                               &queue[i],
9703                               jobid,
9704                               i,
9705                               snum,
9706                               pinfo2,
9707                               devmode);
9708 }
9709
9710 /****************************************************************
9711  _spoolss_GetJob
9712 ****************************************************************/
9713
9714 WERROR _spoolss_GetJob(struct pipes_struct *p,
9715                        struct spoolss_GetJob *r)
9716 {
9717         WERROR result = WERR_OK;
9718         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9719         const char *svc_name;
9720         int sysjob;
9721         int snum;
9722         int count;
9723         struct tdb_print_db *pdb;
9724         print_queue_struct      *queue = NULL;
9725         print_status_struct prt_status;
9726
9727         /* that's an [in out] buffer */
9728
9729         if (!r->in.buffer && (r->in.offered != 0)) {
9730                 result = WERR_INVALID_PARAMETER;
9731                 goto err_jinfo_free;
9732         }
9733
9734         DEBUG(5,("_spoolss_GetJob\n"));
9735
9736         *r->out.needed = 0;
9737
9738         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9739                 result = WERR_INVALID_HANDLE;
9740                 goto err_jinfo_free;
9741         }
9742
9743         svc_name = lp_const_servicename(snum);
9744         if (svc_name == NULL) {
9745                 result = WERR_INVALID_PARAMETER;
9746                 goto err_jinfo_free;
9747         }
9748
9749         result = winreg_get_printer_internal(p->mem_ctx,
9750                                     get_session_info_system(),
9751                                     p->msg_ctx,
9752                                     svc_name,
9753                                     &pinfo2);
9754         if (!W_ERROR_IS_OK(result)) {
9755                 goto err_jinfo_free;
9756         }
9757
9758         pdb = get_print_db_byname(svc_name);
9759         if (pdb == NULL) {
9760                 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9761                 result = WERR_INVALID_PARAMETER;
9762                 goto err_pinfo_free;
9763         }
9764
9765         sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9766         release_print_db(pdb);
9767         if (sysjob == -1) {
9768                 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9769                 result = WERR_INVALID_PARAMETER;
9770                 goto err_pinfo_free;
9771         }
9772
9773         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9774
9775         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9776                      count, prt_status.status, prt_status.message));
9777
9778         switch (r->in.level) {
9779         case 1:
9780                 result = getjob_level_1(p->mem_ctx,
9781                                         queue, count, snum, pinfo2,
9782                                         r->in.job_id, sysjob,
9783                                         &r->out.info->info1);
9784                 break;
9785         case 2:
9786                 result = getjob_level_2(p->mem_ctx,
9787                                         queue, count, snum, pinfo2,
9788                                         r->in.job_id, sysjob,
9789                                         &r->out.info->info2);
9790                 break;
9791         default:
9792                 result = WERR_INVALID_LEVEL;
9793                 break;
9794         }
9795
9796         SAFE_FREE(queue);
9797         TALLOC_FREE(pinfo2);
9798
9799         if (!W_ERROR_IS_OK(result)) {
9800                 goto err_jinfo_free;
9801         }
9802
9803         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9804                                                                                    r->in.level);
9805         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9806
9807         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9808
9809 err_pinfo_free:
9810         TALLOC_FREE(pinfo2);
9811 err_jinfo_free:
9812         TALLOC_FREE(r->out.info);
9813         return result;
9814 }
9815
9816 /****************************************************************
9817  _spoolss_GetPrinterDataEx
9818 ****************************************************************/
9819
9820 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9821                                  struct spoolss_GetPrinterDataEx *r)
9822 {
9823
9824         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9825         const char *printer;
9826         int                     snum = 0;
9827         WERROR result = WERR_OK;
9828         DATA_BLOB blob;
9829         enum winreg_Type val_type = REG_NONE;
9830         uint8_t *val_data = NULL;
9831         uint32_t val_size = 0;
9832         struct dcerpc_binding_handle *b;
9833         TALLOC_CTX *tmp_ctx;
9834
9835         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9836
9837         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9838                 r->in.key_name, r->in.value_name));
9839
9840         /* in case of problem, return some default values */
9841
9842         *r->out.needed  = 0;
9843         *r->out.type    = REG_NONE;
9844
9845         tmp_ctx = talloc_new(p->mem_ctx);
9846         if (!tmp_ctx) {
9847                 return WERR_NOT_ENOUGH_MEMORY;
9848         }
9849
9850         if (!Printer) {
9851                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9852                         OUR_HANDLE(r->in.handle)));
9853                 result = WERR_INVALID_HANDLE;
9854                 goto done;
9855         }
9856
9857         /* Is the handle to a printer or to the server? */
9858
9859         if (Printer->printer_type == SPLHND_SERVER) {
9860
9861                 union spoolss_PrinterData data;
9862
9863                 result = getprinterdata_printer_server(tmp_ctx,
9864                                                        r->in.value_name,
9865                                                        r->out.type,
9866                                                        &data);
9867                 if (!W_ERROR_IS_OK(result)) {
9868                         goto done;
9869                 }
9870
9871                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9872                                                   *r->out.type, &data);
9873                 if (!W_ERROR_IS_OK(result)) {
9874                         goto done;
9875                 }
9876
9877                 *r->out.needed = blob.length;
9878
9879                 if (r->in.offered >= *r->out.needed) {
9880                         memcpy(r->out.data, blob.data, blob.length);
9881                 }
9882
9883                 result = WERR_OK;
9884                 goto done;
9885         }
9886
9887         /* check to see if the keyname is valid */
9888         if (!strlen(r->in.key_name)) {
9889                 result = WERR_INVALID_PARAMETER;
9890                 goto done;
9891         }
9892
9893         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9894                 result = WERR_INVALID_HANDLE;
9895                 goto done;
9896         }
9897         printer = lp_const_servicename(snum);
9898
9899         result = winreg_printer_binding_handle(tmp_ctx,
9900                                                get_session_info_system(),
9901                                                p->msg_ctx,
9902                                                &b);
9903         if (!W_ERROR_IS_OK(result)) {
9904                 goto done;
9905         }
9906
9907         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9908         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9909             strequal(r->in.value_name, "ChangeId")) {
9910                 *r->out.type = REG_DWORD;
9911                 *r->out.needed = 4;
9912                 if (r->in.offered >= *r->out.needed) {
9913                         uint32_t changeid = 0;
9914
9915                         result = winreg_printer_get_changeid(tmp_ctx, b,
9916                                                              printer,
9917                                                              &changeid);
9918                         if (!W_ERROR_IS_OK(result)) {
9919                                 goto done;
9920                         }
9921
9922                         SIVAL(r->out.data, 0, changeid);
9923                         result = WERR_OK;
9924                 }
9925                 goto done;
9926         }
9927
9928         result = winreg_get_printer_dataex(tmp_ctx, b,
9929                                            printer,
9930                                            r->in.key_name,
9931                                            r->in.value_name,
9932                                            &val_type,
9933                                            &val_data,
9934                                            &val_size);
9935         if (!W_ERROR_IS_OK(result)) {
9936                 goto done;
9937         }
9938
9939         *r->out.needed = val_size;
9940         *r->out.type = val_type;
9941
9942         if (r->in.offered >= *r->out.needed) {
9943                 memcpy(r->out.data, val_data, val_size);
9944         }
9945
9946 done:
9947         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9948
9949         if (W_ERROR_IS_OK(result)) {
9950                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9951         }
9952
9953         talloc_free(tmp_ctx);
9954         return result;
9955 }
9956
9957 /****************************************************************
9958  _spoolss_SetPrinterDataEx
9959 ****************************************************************/
9960
9961 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9962                                  struct spoolss_SetPrinterDataEx *r)
9963 {
9964         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9965         int                     snum = 0;
9966         WERROR                  result = WERR_OK;
9967         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9968         char                    *oid_string;
9969         struct dcerpc_binding_handle *b;
9970         TALLOC_CTX *tmp_ctx;
9971
9972         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9973
9974         /* From MSDN documentation of SetPrinterDataEx: pass request to
9975            SetPrinterData if key is "PrinterDriverData" */
9976
9977         if (!Printer) {
9978                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9979                         OUR_HANDLE(r->in.handle)));
9980                 return WERR_INVALID_HANDLE;
9981         }
9982
9983         if (Printer->printer_type == SPLHND_SERVER) {
9984                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9985                         "Not implemented for server handles yet\n"));
9986                 return WERR_INVALID_PARAMETER;
9987         }
9988
9989         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9990                 return WERR_INVALID_HANDLE;
9991         }
9992
9993         /*
9994          * Access check : NT returns "access denied" if you make a
9995          * SetPrinterData call without the necessary privildge.
9996          * we were originally returning OK if nothing changed
9997          * which made Win2k issue **a lot** of SetPrinterData
9998          * when connecting to a printer  --jerry
9999          */
10000
10001         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10002                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
10003                         "change denied by handle access permissions\n"));
10004                 return WERR_ACCESS_DENIED;
10005         }
10006
10007         tmp_ctx = talloc_new(p->mem_ctx);
10008         if (!tmp_ctx) {
10009                 return WERR_NOT_ENOUGH_MEMORY;
10010         }
10011
10012         result = winreg_printer_binding_handle(tmp_ctx,
10013                                                get_session_info_system(),
10014                                                p->msg_ctx,
10015                                                &b);
10016         if (!W_ERROR_IS_OK(result)) {
10017                 goto done;
10018         }
10019
10020         result = winreg_get_printer(tmp_ctx, b,
10021                                     lp_servicename(talloc_tos(), snum),
10022                                     &pinfo2);
10023         if (!W_ERROR_IS_OK(result)) {
10024                 goto done;
10025         }
10026
10027         /* check for OID in valuename */
10028
10029         oid_string = strchr(r->in.value_name, ',');
10030         if (oid_string) {
10031                 *oid_string = '\0';
10032                 oid_string++;
10033         }
10034
10035         /* save the registry data */
10036
10037         result = winreg_set_printer_dataex(tmp_ctx, b,
10038                                            pinfo2->sharename,
10039                                            r->in.key_name,
10040                                            r->in.value_name,
10041                                            r->in.type,
10042                                            r->in.data,
10043                                            r->in.offered);
10044
10045         if (W_ERROR_IS_OK(result)) {
10046                 /* save the OID if one was specified */
10047                 if (oid_string) {
10048                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
10049                                 r->in.key_name, SPOOL_OID_KEY);
10050                         if (!str) {
10051                                 result = WERR_NOT_ENOUGH_MEMORY;
10052                                 goto done;
10053                         }
10054
10055                         /*
10056                          * I'm not checking the status here on purpose.  Don't know
10057                          * if this is right, but I'm returning the status from the
10058                          * previous set_printer_dataex() call.  I have no idea if
10059                          * this is right.    --jerry
10060                          */
10061                         winreg_set_printer_dataex(tmp_ctx, b,
10062                                                   pinfo2->sharename,
10063                                                   str,
10064                                                   r->in.value_name,
10065                                                   REG_SZ,
10066                                                   (uint8_t *) oid_string,
10067                                                   strlen(oid_string) + 1);
10068                 }
10069
10070                 result = winreg_printer_update_changeid(tmp_ctx, b,
10071                                                         lp_const_servicename(snum));
10072
10073         }
10074
10075 done:
10076         talloc_free(tmp_ctx);
10077         return result;
10078 }
10079
10080 /****************************************************************
10081  _spoolss_DeletePrinterDataEx
10082 ****************************************************************/
10083
10084 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
10085                                     struct spoolss_DeletePrinterDataEx *r)
10086 {
10087         const char *printer;
10088         int             snum=0;
10089         WERROR          status = WERR_OK;
10090         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10091
10092         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
10093
10094         if (!Printer) {
10095                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
10096                         "Invalid handle (%s:%u:%u).\n",
10097                         OUR_HANDLE(r->in.handle)));
10098                 return WERR_INVALID_HANDLE;
10099         }
10100
10101         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10102                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
10103                         "printer properties change denied by handle\n"));
10104                 return WERR_ACCESS_DENIED;
10105         }
10106
10107         if (!r->in.value_name || !r->in.key_name) {
10108                 return WERR_NOT_ENOUGH_MEMORY;
10109         }
10110
10111         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10112                 return WERR_INVALID_HANDLE;
10113         }
10114         printer = lp_const_servicename(snum);
10115
10116         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
10117                                               get_session_info_system(),
10118                                               p->msg_ctx,
10119                                               printer,
10120                                               r->in.key_name,
10121                                               r->in.value_name);
10122         if (W_ERROR_IS_OK(status)) {
10123                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
10124                                                         get_session_info_system(),
10125                                                         p->msg_ctx,
10126                                                         printer);
10127         }
10128
10129         return status;
10130 }
10131
10132 /****************************************************************
10133  _spoolss_EnumPrinterKey
10134 ****************************************************************/
10135
10136 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
10137                                struct spoolss_EnumPrinterKey *r)
10138 {
10139         uint32_t        num_keys;
10140         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10141         int             snum = 0;
10142         WERROR          result = WERR_FILE_NOT_FOUND;
10143         const char **array = NULL;
10144         DATA_BLOB blob;
10145
10146         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
10147
10148         if (!Printer) {
10149                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
10150                         OUR_HANDLE(r->in.handle)));
10151                 return WERR_INVALID_HANDLE;
10152         }
10153
10154         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10155                 return WERR_INVALID_HANDLE;
10156         }
10157
10158         result = winreg_enum_printer_key_internal(p->mem_ctx,
10159                                          get_session_info_system(),
10160                                          p->msg_ctx,
10161                                          lp_const_servicename(snum),
10162                                          r->in.key_name,
10163                                          &num_keys,
10164                                          &array);
10165         if (!W_ERROR_IS_OK(result)) {
10166                 goto done;
10167         }
10168
10169         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
10170                 result = WERR_NOT_ENOUGH_MEMORY;
10171                 goto done;
10172         }
10173
10174         *r->out._ndr_size = r->in.offered / 2;
10175         *r->out.needed = blob.length;
10176
10177         if (r->in.offered < *r->out.needed) {
10178                 result = WERR_MORE_DATA;
10179         } else {
10180                 result = WERR_OK;
10181                 r->out.key_buffer->string_array = array;
10182         }
10183
10184  done:
10185         if (!W_ERROR_IS_OK(result)) {
10186                 TALLOC_FREE(array);
10187                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
10188                         *r->out.needed = 0;
10189                 }
10190         }
10191
10192         return result;
10193 }
10194
10195 /****************************************************************
10196  _spoolss_DeletePrinterKey
10197 ****************************************************************/
10198
10199 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
10200                                  struct spoolss_DeletePrinterKey *r)
10201 {
10202         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10203         int                     snum=0;
10204         WERROR                  status;
10205         const char *printer;
10206         struct dcerpc_binding_handle *b;
10207         TALLOC_CTX *tmp_ctx;
10208
10209         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10210
10211         if (!Printer) {
10212                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10213                         OUR_HANDLE(r->in.handle)));
10214                 return WERR_INVALID_HANDLE;
10215         }
10216
10217         /* if keyname == NULL, return error */
10218         if ( !r->in.key_name )
10219                 return WERR_INVALID_PARAMETER;
10220
10221         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10222                 return WERR_INVALID_HANDLE;
10223         }
10224
10225         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10226                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
10227                         "printer properties change denied by handle\n"));
10228                 return WERR_ACCESS_DENIED;
10229         }
10230
10231         printer = lp_const_servicename(snum);
10232
10233         tmp_ctx = talloc_new(p->mem_ctx);
10234         if (!tmp_ctx) {
10235                 return WERR_NOT_ENOUGH_MEMORY;
10236         }
10237
10238         status = winreg_printer_binding_handle(tmp_ctx,
10239                                                get_session_info_system(),
10240                                                p->msg_ctx,
10241                                                &b);
10242         if (!W_ERROR_IS_OK(status)) {
10243                 goto done;
10244         }
10245
10246         /* delete the key and all subkeys */
10247         status = winreg_delete_printer_key(tmp_ctx, b,
10248                                            printer,
10249                                            r->in.key_name);
10250         if (W_ERROR_IS_OK(status)) {
10251                 status = winreg_printer_update_changeid(tmp_ctx, b,
10252                                                         printer);
10253         }
10254
10255 done:
10256         talloc_free(tmp_ctx);
10257         return status;
10258 }
10259
10260 /****************************************************************
10261  _spoolss_EnumPrinterDataEx
10262 ****************************************************************/
10263
10264 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10265                                   struct spoolss_EnumPrinterDataEx *r)
10266 {
10267         uint32_t        count = 0;
10268         struct spoolss_PrinterEnumValues *info = NULL;
10269         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10270         int             snum;
10271         WERROR          result;
10272
10273         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10274
10275         *r->out.count = 0;
10276         *r->out.needed = 0;
10277         *r->out.info = NULL;
10278
10279         if (!Printer) {
10280                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10281                         OUR_HANDLE(r->in.handle)));
10282                 return WERR_INVALID_HANDLE;
10283         }
10284
10285         /*
10286          * first check for a keyname of NULL or "".  Win2k seems to send
10287          * this a lot and we should send back WERR_INVALID_PARAMETER
10288          * no need to spend time looking up the printer in this case.
10289          * --jerry
10290          */
10291
10292         if (!strlen(r->in.key_name)) {
10293                 result = WERR_INVALID_PARAMETER;
10294                 goto done;
10295         }
10296
10297         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10298                 return WERR_INVALID_HANDLE;
10299         }
10300
10301         /* now look for a match on the key name */
10302         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10303                                             get_session_info_system(),
10304                                             p->msg_ctx,
10305                                             lp_const_servicename(snum),
10306                                             r->in.key_name,
10307                                             &count,
10308                                             &info);
10309         if (!W_ERROR_IS_OK(result)) {
10310                 goto done;
10311         }
10312
10313 #if 0 /* FIXME - gd */
10314         /* housekeeping information in the reply */
10315
10316         /* Fix from Martin Zielinski <mz@seh.de> - ensure
10317          * the hand marshalled container size is a multiple
10318          * of 4 bytes for RPC alignment.
10319          */
10320
10321         if (needed % 4) {
10322                 needed += 4-(needed % 4);
10323         }
10324 #endif
10325         *r->out.count   = count;
10326         *r->out.info    = info;
10327
10328  done:
10329         if (!W_ERROR_IS_OK(result)) {
10330                 return result;
10331         }
10332
10333         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10334                                                spoolss_EnumPrinterDataEx,
10335                                                *r->out.info,
10336                                                *r->out.count);
10337         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10338         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10339
10340         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10341 }
10342
10343 /****************************************************************************
10344 ****************************************************************************/
10345
10346 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10347                                                  const char *servername,
10348                                                  const char *environment,
10349                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
10350 {
10351         WERROR werr;
10352         char *path = NULL;
10353
10354         werr = compose_spoolss_server_path(mem_ctx,
10355                                            servername,
10356                                            environment,
10357                                            SPOOLSS_PRTPROCS_PATH,
10358                                            &path);
10359         if (!W_ERROR_IS_OK(werr)) {
10360                 return werr;
10361         }
10362
10363         DEBUG(4,("print processor directory: [%s]\n", path));
10364
10365         r->directory_name = path;
10366
10367         return WERR_OK;
10368 }
10369
10370 /****************************************************************
10371  _spoolss_GetPrintProcessorDirectory
10372 ****************************************************************/
10373
10374 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10375                                            struct spoolss_GetPrintProcessorDirectory *r)
10376 {
10377         WERROR result;
10378         char *prnproc_share = NULL;
10379         bool prnproc_share_exists = false;
10380         int snum;
10381
10382         /* that's an [in out] buffer */
10383
10384         if (!r->in.buffer && (r->in.offered != 0)) {
10385                 result = WERR_INVALID_PARAMETER;
10386                 goto err_info_free;
10387         }
10388
10389         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10390                 r->in.level));
10391
10392         *r->out.needed = 0;
10393
10394         /* r->in.level is ignored */
10395
10396         /* We always should reply with a local print processor directory so that
10397          * users are not forced to have a [prnproc$] share on the Samba spoolss
10398          * server, if users decide to do so, lets announce it though - Guenther */
10399
10400         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10401         if (!prnproc_share) {
10402                 result = WERR_NOT_ENOUGH_MEMORY;
10403                 goto err_info_free;
10404         }
10405         if (snum != -1) {
10406                 prnproc_share_exists = true;
10407         }
10408
10409         result = getprintprocessordirectory_level_1(p->mem_ctx,
10410                                                     prnproc_share_exists ? r->in.server : NULL,
10411                                                     r->in.environment,
10412                                                     &r->out.info->info1);
10413         if (!W_ERROR_IS_OK(result)) {
10414                 goto err_info_free;
10415         }
10416
10417         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10418                                                                                    r->out.info, r->in.level);
10419         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10420
10421         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10422
10423 err_info_free:
10424         TALLOC_FREE(r->out.info);
10425         return result;
10426 }
10427
10428 /*******************************************************************
10429  ********************************************************************/
10430
10431 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10432                                const char *dllname)
10433 {
10434         enum ndr_err_code ndr_err;
10435         struct spoolss_MonitorUi ui;
10436
10437         ui.dll_name = dllname;
10438
10439         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10440                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10441         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10442                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10443         }
10444         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10445 }
10446
10447 /*******************************************************************
10448  Streams the monitor UI DLL name in UNICODE
10449 *******************************************************************/
10450
10451 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10452                                struct security_token *token, DATA_BLOB *in,
10453                                DATA_BLOB *out, uint32_t *needed)
10454 {
10455         const char *dllname = "tcpmonui.dll";
10456
10457         *needed = (strlen(dllname)+1) * 2;
10458
10459         if (out->length < *needed) {
10460                 return WERR_INSUFFICIENT_BUFFER;
10461         }
10462
10463         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10464                 return WERR_NOT_ENOUGH_MEMORY;
10465         }
10466
10467         return WERR_OK;
10468 }
10469
10470 /*******************************************************************
10471  ********************************************************************/
10472
10473 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10474                              struct spoolss_PortData1 *port1,
10475                              const DATA_BLOB *buf)
10476 {
10477         enum ndr_err_code ndr_err;
10478         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10479                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10480         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10481                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10482         }
10483         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10484 }
10485
10486 /*******************************************************************
10487  ********************************************************************/
10488
10489 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10490                              struct spoolss_PortData2 *port2,
10491                              const DATA_BLOB *buf)
10492 {
10493         enum ndr_err_code ndr_err;
10494         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10495                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10496         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10497                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10498         }
10499         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10500 }
10501
10502 /*******************************************************************
10503  Create a new TCP/IP port
10504 *******************************************************************/
10505
10506 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10507                              struct security_token *token, DATA_BLOB *in,
10508                              DATA_BLOB *out, uint32_t *needed)
10509 {
10510         struct spoolss_PortData1 port1;
10511         struct spoolss_PortData2 port2;
10512         char *device_uri = NULL;
10513         uint32_t version;
10514
10515         const char *portname;
10516         const char *hostaddress;
10517         const char *queue;
10518         uint32_t port_number;
10519         uint32_t protocol;
10520
10521         /* peek for spoolss_PortData version */
10522
10523         if (!in || (in->length < (128 + 4))) {
10524                 return WERR_GEN_FAILURE;
10525         }
10526
10527         version = IVAL(in->data, 128);
10528
10529         switch (version) {
10530                 case 1:
10531                         ZERO_STRUCT(port1);
10532
10533                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10534                                 return WERR_NOT_ENOUGH_MEMORY;
10535                         }
10536
10537                         portname        = port1.portname;
10538                         hostaddress     = port1.hostaddress;
10539                         queue           = port1.queue;
10540                         protocol        = port1.protocol;
10541                         port_number     = port1.port_number;
10542
10543                         break;
10544                 case 2:
10545                         ZERO_STRUCT(port2);
10546
10547                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10548                                 return WERR_NOT_ENOUGH_MEMORY;
10549                         }
10550
10551                         portname        = port2.portname;
10552                         hostaddress     = port2.hostaddress;
10553                         queue           = port2.queue;
10554                         protocol        = port2.protocol;
10555                         port_number     = port2.port_number;
10556
10557                         break;
10558                 default:
10559                         DEBUG(1,("xcvtcp_addport: "
10560                                 "unknown version of port_data: %d\n", version));
10561                         return WERR_UNKNOWN_PORT;
10562         }
10563
10564         /* create the device URI and call the add_port_hook() */
10565
10566         switch (protocol) {
10567         case PROTOCOL_RAWTCP_TYPE:
10568                 device_uri = talloc_asprintf(mem_ctx,
10569                                 "socket://%s:%d/", hostaddress,
10570                                 port_number);
10571                 break;
10572
10573         case PROTOCOL_LPR_TYPE:
10574                 device_uri = talloc_asprintf(mem_ctx,
10575                         "lpr://%s/%s", hostaddress, queue );
10576                 break;
10577
10578         default:
10579                 return WERR_UNKNOWN_PORT;
10580         }
10581
10582         if (!device_uri) {
10583                 return WERR_NOT_ENOUGH_MEMORY;
10584         }
10585
10586         return add_port_hook(mem_ctx, token, portname, device_uri);
10587 }
10588
10589 /*******************************************************************
10590 *******************************************************************/
10591
10592 struct xcv_api_table xcvtcp_cmds[] = {
10593         { "MonitorUI",  xcvtcp_monitorui },
10594         { "AddPort",    xcvtcp_addport},
10595         { NULL,         NULL }
10596 };
10597
10598 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10599                                      struct security_token *token, const char *command,
10600                                      DATA_BLOB *inbuf,
10601                                      DATA_BLOB *outbuf,
10602                                      uint32_t *needed )
10603 {
10604         int i;
10605
10606         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10607
10608         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10609                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10610                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10611         }
10612
10613         return WERR_INVALID_FUNCTION;
10614 }
10615
10616 /*******************************************************************
10617 *******************************************************************/
10618 #if 0   /* don't support management using the "Local Port" monitor */
10619
10620 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10621                                  struct security_token *token, DATA_BLOB *in,
10622                                  DATA_BLOB *out, uint32_t *needed)
10623 {
10624         const char *dllname = "localui.dll";
10625
10626         *needed = (strlen(dllname)+1) * 2;
10627
10628         if (out->length < *needed) {
10629                 return WERR_INSUFFICIENT_BUFFER;
10630         }
10631
10632         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10633                 return WERR_NOT_ENOUGH_MEMORY;
10634         }
10635
10636         return WERR_OK;
10637 }
10638
10639 /*******************************************************************
10640 *******************************************************************/
10641
10642 struct xcv_api_table xcvlocal_cmds[] = {
10643         { "MonitorUI",  xcvlocal_monitorui },
10644         { NULL,         NULL }
10645 };
10646 #else
10647 struct xcv_api_table xcvlocal_cmds[] = {
10648         { NULL,         NULL }
10649 };
10650 #endif
10651
10652
10653
10654 /*******************************************************************
10655 *******************************************************************/
10656
10657 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10658                                        struct security_token *token, const char *command,
10659                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10660                                        uint32_t *needed)
10661 {
10662         int i;
10663
10664         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10665
10666         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10667                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10668                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10669         }
10670         return WERR_INVALID_FUNCTION;
10671 }
10672
10673 /****************************************************************
10674  _spoolss_XcvData
10675 ****************************************************************/
10676
10677 WERROR _spoolss_XcvData(struct pipes_struct *p,
10678                         struct spoolss_XcvData *r)
10679 {
10680         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10681         DATA_BLOB out_data = data_blob_null;
10682         WERROR werror;
10683
10684         if (!Printer) {
10685                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10686                         OUR_HANDLE(r->in.handle)));
10687                 return WERR_INVALID_HANDLE;
10688         }
10689
10690         /* Has to be a handle to the TCP/IP port monitor */
10691
10692         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10693                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10694                 return WERR_INVALID_HANDLE;
10695         }
10696
10697         /* requires administrative access to the server */
10698
10699         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10700                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10701                 return WERR_ACCESS_DENIED;
10702         }
10703
10704         /* Allocate the outgoing buffer */
10705
10706         if (r->in.out_data_size) {
10707                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10708                 if (out_data.data == NULL) {
10709                         return WERR_NOT_ENOUGH_MEMORY;
10710                 }
10711         }
10712
10713         switch ( Printer->printer_type ) {
10714         case SPLHND_PORTMON_TCP:
10715                 werror = process_xcvtcp_command(p->mem_ctx,
10716                                                 p->session_info->security_token,
10717                                                 r->in.function_name,
10718                                                 &r->in.in_data, &out_data,
10719                                                 r->out.needed);
10720                 break;
10721         case SPLHND_PORTMON_LOCAL:
10722                 werror = process_xcvlocal_command(p->mem_ctx,
10723                                                   p->session_info->security_token,
10724                                                   r->in.function_name,
10725                                                   &r->in.in_data, &out_data,
10726                                                   r->out.needed);
10727                 break;
10728         default:
10729                 werror = WERR_INVALID_PRINT_MONITOR;
10730         }
10731
10732         if (!W_ERROR_IS_OK(werror)) {
10733                 return werror;
10734         }
10735
10736         *r->out.status_code = 0;
10737
10738         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10739                 memcpy(r->out.out_data, out_data.data,
10740                         MIN(r->in.out_data_size, out_data.length));
10741         }
10742
10743         return WERR_OK;
10744 }
10745
10746 /****************************************************************
10747  _spoolss_AddPrintProcessor
10748 ****************************************************************/
10749
10750 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10751                                   struct spoolss_AddPrintProcessor *r)
10752 {
10753         /* for now, just indicate success and ignore the add.  We'll
10754            automatically set the winprint processor for printer
10755            entries later.  Used to debug the LexMark Optra S 1855 PCL
10756            driver --jerry */
10757
10758         return WERR_OK;
10759 }
10760
10761 /****************************************************************
10762  _spoolss_AddPort
10763 ****************************************************************/
10764
10765 WERROR _spoolss_AddPort(struct pipes_struct *p,
10766                         struct spoolss_AddPort *r)
10767 {
10768         /* do what w2k3 does */
10769
10770         return WERR_NOT_SUPPORTED;
10771 }
10772
10773 /****************************************************************
10774  _spoolss_GetPrinterDriver
10775 ****************************************************************/
10776
10777 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10778                                  struct spoolss_GetPrinterDriver *r)
10779 {
10780         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10781         return WERR_NOT_SUPPORTED;
10782 }
10783
10784 /****************************************************************
10785  _spoolss_ReadPrinter
10786 ****************************************************************/
10787
10788 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10789                             struct spoolss_ReadPrinter *r)
10790 {
10791         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10792         return WERR_NOT_SUPPORTED;
10793 }
10794
10795 /****************************************************************
10796  _spoolss_WaitForPrinterChange
10797 ****************************************************************/
10798
10799 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10800                                      struct spoolss_WaitForPrinterChange *r)
10801 {
10802         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10803         return WERR_NOT_SUPPORTED;
10804 }
10805
10806 /****************************************************************
10807  _spoolss_ConfigurePort
10808 ****************************************************************/
10809
10810 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10811                               struct spoolss_ConfigurePort *r)
10812 {
10813         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10814         return WERR_NOT_SUPPORTED;
10815 }
10816
10817 /****************************************************************
10818  _spoolss_DeletePort
10819 ****************************************************************/
10820
10821 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10822                            struct spoolss_DeletePort *r)
10823 {
10824         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10825         return WERR_NOT_SUPPORTED;
10826 }
10827
10828 /****************************************************************
10829  _spoolss_CreatePrinterIC
10830 ****************************************************************/
10831
10832 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10833                                 struct spoolss_CreatePrinterIC *r)
10834 {
10835         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10836         return WERR_NOT_SUPPORTED;
10837 }
10838
10839 /****************************************************************
10840  _spoolss_PlayGDIScriptOnPrinterIC
10841 ****************************************************************/
10842
10843 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10844                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10845 {
10846         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10847         return WERR_NOT_SUPPORTED;
10848 }
10849
10850 /****************************************************************
10851  _spoolss_DeletePrinterIC
10852 ****************************************************************/
10853
10854 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10855                                 struct spoolss_DeletePrinterIC *r)
10856 {
10857         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10858         return WERR_NOT_SUPPORTED;
10859 }
10860
10861 /****************************************************************
10862  _spoolss_AddPrinterConnection
10863 ****************************************************************/
10864
10865 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10866                                      struct spoolss_AddPrinterConnection *r)
10867 {
10868         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10869         return WERR_NOT_SUPPORTED;
10870 }
10871
10872 /****************************************************************
10873  _spoolss_DeletePrinterConnection
10874 ****************************************************************/
10875
10876 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10877                                         struct spoolss_DeletePrinterConnection *r)
10878 {
10879         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10880         return WERR_NOT_SUPPORTED;
10881 }
10882
10883 /****************************************************************
10884  _spoolss_PrinterMessageBox
10885 ****************************************************************/
10886
10887 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10888                                   struct spoolss_PrinterMessageBox *r)
10889 {
10890         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10891         return WERR_NOT_SUPPORTED;
10892 }
10893
10894 /****************************************************************
10895  _spoolss_AddMonitor
10896 ****************************************************************/
10897
10898 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10899                            struct spoolss_AddMonitor *r)
10900 {
10901         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10902         return WERR_NOT_SUPPORTED;
10903 }
10904
10905 /****************************************************************
10906  _spoolss_DeleteMonitor
10907 ****************************************************************/
10908
10909 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10910                               struct spoolss_DeleteMonitor *r)
10911 {
10912         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10913         return WERR_NOT_SUPPORTED;
10914 }
10915
10916 /****************************************************************
10917  _spoolss_DeletePrintProcessor
10918 ****************************************************************/
10919
10920 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10921                                      struct spoolss_DeletePrintProcessor *r)
10922 {
10923         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10924         return WERR_NOT_SUPPORTED;
10925 }
10926
10927 /****************************************************************
10928  _spoolss_AddPrintProvidor
10929 ****************************************************************/
10930
10931 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10932                                  struct spoolss_AddPrintProvidor *r)
10933 {
10934         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10935         return WERR_NOT_SUPPORTED;
10936 }
10937
10938 /****************************************************************
10939  _spoolss_DeletePrintProvidor
10940 ****************************************************************/
10941
10942 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10943                                     struct spoolss_DeletePrintProvidor *r)
10944 {
10945         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10946         return WERR_NOT_SUPPORTED;
10947 }
10948
10949 /****************************************************************
10950  _spoolss_FindFirstPrinterChangeNotification
10951 ****************************************************************/
10952
10953 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10954                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10955 {
10956         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10957         return WERR_NOT_SUPPORTED;
10958 }
10959
10960 /****************************************************************
10961  _spoolss_FindNextPrinterChangeNotification
10962 ****************************************************************/
10963
10964 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10965                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10966 {
10967         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10968         return WERR_NOT_SUPPORTED;
10969 }
10970
10971 /****************************************************************
10972  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10973 ****************************************************************/
10974
10975 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10976                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10977 {
10978         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10979         return WERR_NOT_SUPPORTED;
10980 }
10981
10982 /****************************************************************
10983  _spoolss_ReplyOpenPrinter
10984 ****************************************************************/
10985
10986 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10987                                  struct spoolss_ReplyOpenPrinter *r)
10988 {
10989         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10990         return WERR_NOT_SUPPORTED;
10991 }
10992
10993 /****************************************************************
10994  _spoolss_RouterReplyPrinter
10995 ****************************************************************/
10996
10997 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10998                                    struct spoolss_RouterReplyPrinter *r)
10999 {
11000         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11001         return WERR_NOT_SUPPORTED;
11002 }
11003
11004 /****************************************************************
11005  _spoolss_ReplyClosePrinter
11006 ****************************************************************/
11007
11008 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
11009                                   struct spoolss_ReplyClosePrinter *r)
11010 {
11011         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11012         return WERR_NOT_SUPPORTED;
11013 }
11014
11015 /****************************************************************
11016  _spoolss_AddPortEx
11017 ****************************************************************/
11018
11019 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
11020                           struct spoolss_AddPortEx *r)
11021 {
11022         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11023         return WERR_NOT_SUPPORTED;
11024 }
11025
11026 /****************************************************************
11027  _spoolss_RouterFindFirstPrinterChangeNotification
11028 ****************************************************************/
11029
11030 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
11031                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
11032 {
11033         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11034         return WERR_NOT_SUPPORTED;
11035 }
11036
11037 /****************************************************************
11038  _spoolss_SpoolerInit
11039 ****************************************************************/
11040
11041 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
11042                             struct spoolss_SpoolerInit *r)
11043 {
11044         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11045         return WERR_NOT_SUPPORTED;
11046 }
11047
11048 /****************************************************************
11049  _spoolss_ResetPrinterEx
11050 ****************************************************************/
11051
11052 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
11053                                struct spoolss_ResetPrinterEx *r)
11054 {
11055         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11056         return WERR_NOT_SUPPORTED;
11057 }
11058
11059 /****************************************************************
11060  _spoolss_RouterReplyPrinterEx
11061 ****************************************************************/
11062
11063 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
11064                                      struct spoolss_RouterReplyPrinterEx *r)
11065 {
11066         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11067         return WERR_NOT_SUPPORTED;
11068 }
11069
11070 /****************************************************************
11071  _spoolss_44
11072 ****************************************************************/
11073
11074 WERROR _spoolss_44(struct pipes_struct *p,
11075                    struct spoolss_44 *r)
11076 {
11077         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11078         return WERR_NOT_SUPPORTED;
11079 }
11080
11081 /****************************************************************
11082  _spoolss_SetPort
11083 ****************************************************************/
11084
11085 WERROR _spoolss_SetPort(struct pipes_struct *p,
11086                         struct spoolss_SetPort *r)
11087 {
11088         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11089         return WERR_NOT_SUPPORTED;
11090 }
11091
11092 /****************************************************************
11093  _spoolss_4a
11094 ****************************************************************/
11095
11096 WERROR _spoolss_4a(struct pipes_struct *p,
11097                    struct spoolss_4a *r)
11098 {
11099         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11100         return WERR_NOT_SUPPORTED;
11101 }
11102
11103 /****************************************************************
11104  _spoolss_4b
11105 ****************************************************************/
11106
11107 WERROR _spoolss_4b(struct pipes_struct *p,
11108                    struct spoolss_4b *r)
11109 {
11110         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11111         return WERR_NOT_SUPPORTED;
11112 }
11113
11114 /****************************************************************
11115  _spoolss_4c
11116 ****************************************************************/
11117
11118 WERROR _spoolss_4c(struct pipes_struct *p,
11119                    struct spoolss_4c *r)
11120 {
11121         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11122         return WERR_NOT_SUPPORTED;
11123 }
11124
11125 /****************************************************************
11126  _spoolss_53
11127 ****************************************************************/
11128
11129 WERROR _spoolss_53(struct pipes_struct *p,
11130                    struct spoolss_53 *r)
11131 {
11132         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11133         return WERR_NOT_SUPPORTED;
11134 }
11135
11136 /****************************************************************
11137  _spoolss_AddPerMachineConnection
11138 ****************************************************************/
11139
11140 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
11141                                         struct spoolss_AddPerMachineConnection *r)
11142 {
11143         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11144         return WERR_NOT_SUPPORTED;
11145 }
11146
11147 /****************************************************************
11148  _spoolss_DeletePerMachineConnection
11149 ****************************************************************/
11150
11151 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
11152                                            struct spoolss_DeletePerMachineConnection *r)
11153 {
11154         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11155         return WERR_NOT_SUPPORTED;
11156 }
11157
11158 /****************************************************************
11159  _spoolss_EnumPerMachineConnections
11160 ****************************************************************/
11161
11162 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
11163                                           struct spoolss_EnumPerMachineConnections *r)
11164 {
11165         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11166         return WERR_NOT_SUPPORTED;
11167 }
11168
11169 /****************************************************************
11170  _spoolss_5a
11171 ****************************************************************/
11172
11173 WERROR _spoolss_5a(struct pipes_struct *p,
11174                    struct spoolss_5a *r)
11175 {
11176         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11177         return WERR_NOT_SUPPORTED;
11178 }
11179
11180 /****************************************************************
11181  _spoolss_5b
11182 ****************************************************************/
11183
11184 WERROR _spoolss_5b(struct pipes_struct *p,
11185                    struct spoolss_5b *r)
11186 {
11187         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11188         return WERR_NOT_SUPPORTED;
11189 }
11190
11191 /****************************************************************
11192  _spoolss_5c
11193 ****************************************************************/
11194
11195 WERROR _spoolss_5c(struct pipes_struct *p,
11196                    struct spoolss_5c *r)
11197 {
11198         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11199         return WERR_NOT_SUPPORTED;
11200 }
11201
11202 /****************************************************************
11203  _spoolss_5d
11204 ****************************************************************/
11205
11206 WERROR _spoolss_5d(struct pipes_struct *p,
11207                    struct spoolss_5d *r)
11208 {
11209         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11210         return WERR_NOT_SUPPORTED;
11211 }
11212
11213 /****************************************************************
11214  _spoolss_5e
11215 ****************************************************************/
11216
11217 WERROR _spoolss_5e(struct pipes_struct *p,
11218                    struct spoolss_5e *r)
11219 {
11220         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11221         return WERR_NOT_SUPPORTED;
11222 }
11223
11224 /****************************************************************
11225  _spoolss_5f
11226 ****************************************************************/
11227
11228 WERROR _spoolss_5f(struct pipes_struct *p,
11229                    struct spoolss_5f *r)
11230 {
11231         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11232         return WERR_NOT_SUPPORTED;
11233 }
11234
11235 /****************************************************************
11236  _spoolss_60
11237 ****************************************************************/
11238
11239 WERROR _spoolss_60(struct pipes_struct *p,
11240                    struct spoolss_60 *r)
11241 {
11242         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11243         return WERR_NOT_SUPPORTED;
11244 }
11245
11246 /****************************************************************
11247  _spoolss_SendRecvBidiData
11248 ****************************************************************/
11249
11250 WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
11251                                  struct spoolss_SendRecvBidiData *r)
11252 {
11253         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11254         return WERR_NOT_SUPPORTED;
11255 }
11256
11257 /****************************************************************
11258  _spoolss_62
11259 ****************************************************************/
11260
11261 WERROR _spoolss_62(struct pipes_struct *p,
11262                    struct spoolss_62 *r)
11263 {
11264         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11265         return WERR_NOT_SUPPORTED;
11266 }
11267
11268 /****************************************************************
11269  _spoolss_63
11270 ****************************************************************/
11271
11272 WERROR _spoolss_63(struct pipes_struct *p,
11273                    struct spoolss_63 *r)
11274 {
11275         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11276         return WERR_NOT_SUPPORTED;
11277 }
11278
11279 /****************************************************************
11280  _spoolss_64
11281 ****************************************************************/
11282
11283 WERROR _spoolss_64(struct pipes_struct *p,
11284                    struct spoolss_64 *r)
11285 {
11286         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11287         return WERR_NOT_SUPPORTED;
11288 }
11289
11290 /****************************************************************
11291  _spoolss_65
11292 ****************************************************************/
11293
11294 WERROR _spoolss_65(struct pipes_struct *p,
11295                    struct spoolss_65 *r)
11296 {
11297         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11298         return WERR_NOT_SUPPORTED;
11299 }
11300
11301 /****************************************************************
11302  _spoolss_GetCorePrinterDrivers
11303 ****************************************************************/
11304
11305 HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11306                                        struct spoolss_GetCorePrinterDrivers *r)
11307 {
11308         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11309         return HRES_ERROR_NOT_SUPPORTED;
11310 }
11311
11312 /****************************************************************
11313  _spoolss_67
11314 ****************************************************************/
11315
11316 WERROR _spoolss_67(struct pipes_struct *p,
11317                    struct spoolss_67 *r)
11318 {
11319         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11320         return WERR_NOT_SUPPORTED;
11321 }
11322
11323 /****************************************************************
11324  _spoolss_GetPrinterDriverPackagePath
11325 ****************************************************************/
11326
11327 HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11328                                              struct spoolss_GetPrinterDriverPackagePath *r)
11329 {
11330         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11331         return HRES_ERROR_NOT_SUPPORTED;
11332 }
11333
11334 /****************************************************************
11335  _spoolss_69
11336 ****************************************************************/
11337
11338 WERROR _spoolss_69(struct pipes_struct *p,
11339                    struct spoolss_69 *r)
11340 {
11341         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11342         return WERR_NOT_SUPPORTED;
11343 }
11344
11345 /****************************************************************
11346  _spoolss_6a
11347 ****************************************************************/
11348
11349 WERROR _spoolss_6a(struct pipes_struct *p,
11350                    struct spoolss_6a *r)
11351 {
11352         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11353         return WERR_NOT_SUPPORTED;
11354 }
11355
11356 /****************************************************************
11357  _spoolss_6b
11358 ****************************************************************/
11359
11360 WERROR _spoolss_6b(struct pipes_struct *p,
11361                    struct spoolss_6b *r)
11362 {
11363         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11364         return WERR_NOT_SUPPORTED;
11365 }
11366
11367 /****************************************************************
11368  _spoolss_6c
11369 ****************************************************************/
11370
11371 WERROR _spoolss_6c(struct pipes_struct *p,
11372                    struct spoolss_6c *r)
11373 {
11374         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11375         return WERR_NOT_SUPPORTED;
11376 }
11377
11378 /****************************************************************
11379  _spoolss_6d
11380 ****************************************************************/
11381
11382 WERROR _spoolss_6d(struct pipes_struct *p,
11383                    struct spoolss_6d *r)
11384 {
11385         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11386         return WERR_NOT_SUPPORTED;
11387 }
11388
11389 /****************************************************************
11390  _spoolss_GetJobNamedPropertyValue
11391 ****************************************************************/
11392
11393 WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
11394                                          struct spoolss_GetJobNamedPropertyValue *r)
11395 {
11396         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11397         return WERR_NOT_SUPPORTED;
11398 }
11399
11400 /****************************************************************
11401  _spoolss_SetJobNamedProperty
11402 ****************************************************************/
11403
11404 WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
11405                                     struct spoolss_SetJobNamedProperty *r)
11406 {
11407         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11408         return WERR_NOT_SUPPORTED;
11409 }
11410
11411 /****************************************************************
11412  _spoolss_DeleteJobNamedProperty
11413 ****************************************************************/
11414
11415 WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
11416                                        struct spoolss_DeleteJobNamedProperty *r)
11417 {
11418         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11419         return WERR_NOT_SUPPORTED;
11420 }
11421
11422 /****************************************************************
11423  _spoolss_EnumJobNamedProperties
11424 ****************************************************************/
11425
11426 WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
11427                                        struct spoolss_EnumJobNamedProperties *r)
11428 {
11429         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11430         return WERR_NOT_SUPPORTED;
11431 }
11432
11433 /****************************************************************
11434  _spoolss_72
11435 ****************************************************************/
11436
11437 WERROR _spoolss_72(struct pipes_struct *p,
11438                    struct spoolss_72 *r)
11439 {
11440         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11441         return WERR_NOT_SUPPORTED;
11442 }
11443
11444 /****************************************************************
11445  _spoolss_73
11446 ****************************************************************/
11447
11448 WERROR _spoolss_73(struct pipes_struct *p,
11449                    struct spoolss_73 *r)
11450 {
11451         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11452         return WERR_NOT_SUPPORTED;
11453 }
11454
11455 /****************************************************************
11456  _spoolss_RpcLogJobInfoForBranchOffice
11457 ****************************************************************/
11458
11459 WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
11460                                           struct spoolss_LogJobInfoForBranchOffice *r)
11461 {
11462         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11463         return WERR_NOT_SUPPORTED;
11464 }