spoolss: clear PrinterInfo on GetPrinter error
[obnox/samba/samba-obnox.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "include/printing.h"
42 #include "secrets.h"
43 #include "../librpc/gen_ndr/netlogon.h"
44 #include "rpc_misc.h"
45 #include "printing/notify.h"
46 #include "serverid.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "smbd/globals.h"
50 #include "auth.h"
51 #include "messages.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
53 #include "util_tdb.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
58 #include "../libcli/smb/smbXcli_base.h"
59
60 /* macros stolen from s4 spoolss server */
61 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
62         ((info)?ndr_size_##fn(info, level, 0):0)
63
64 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
65         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
66
67 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
68         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
69
70 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
71
72 #undef DBGC_CLASS
73 #define DBGC_CLASS DBGC_RPC_SRV
74
75 #ifndef MAX_OPEN_PRINTER_EXS
76 #define MAX_OPEN_PRINTER_EXS 50
77 #endif
78
79 struct notify_back_channel;
80
81 /* structure to store the printer handles */
82 /* and a reference to what it's pointing to */
83 /* and the notify info asked about */
84 /* that's the central struct */
85 struct printer_handle {
86         struct printer_handle *prev, *next;
87         bool document_started;
88         bool page_started;
89         uint32 jobid; /* jobid in printing backend */
90         int printer_type;
91         const char *servername;
92         fstring sharename;
93         uint32 type;
94         uint32 access_granted;
95         struct {
96                 uint32 flags;
97                 uint32 options;
98                 fstring localmachine;
99                 uint32 printerlocal;
100                 struct spoolss_NotifyOption *option;
101                 struct policy_handle cli_hnd;
102                 struct notify_back_channel *cli_chan;
103                 uint32 change;
104                 /* are we in a FindNextPrinterChangeNotify() call? */
105                 bool fnpcn;
106                 struct messaging_context *msg_ctx;
107         } notify;
108         struct {
109                 fstring machine;
110                 fstring user;
111         } client;
112
113         /* devmode sent in the OpenPrinter() call */
114         struct spoolss_DeviceMode *devmode;
115
116         /* TODO cache the printer info2 structure */
117         struct spoolss_PrinterInfo2 *info2;
118
119 };
120
121 static struct printer_handle *printers_list;
122
123 struct printer_session_counter {
124         struct printer_session_counter *next;
125         struct printer_session_counter *prev;
126
127         int snum;
128         uint32_t counter;
129 };
130
131 static struct printer_session_counter *counter_list;
132
133 struct notify_back_channel {
134         struct notify_back_channel *prev, *next;
135
136         /* associated client */
137         struct sockaddr_storage client_address;
138
139         /* print notify back-channel pipe handle*/
140         struct rpc_pipe_client *cli_pipe;
141         struct cli_state *cli;
142         uint32_t active_connections;
143 };
144
145 static struct notify_back_channel *back_channels;
146
147 /* Map generic permissions to printer object specific permissions */
148
149 const struct standard_mapping printer_std_mapping = {
150         PRINTER_READ,
151         PRINTER_WRITE,
152         PRINTER_EXECUTE,
153         PRINTER_ALL_ACCESS
154 };
155
156 /* Map generic permissions to print server object specific permissions */
157
158 const struct standard_mapping printserver_std_mapping = {
159         SERVER_READ,
160         SERVER_WRITE,
161         SERVER_EXECUTE,
162         SERVER_ALL_ACCESS
163 };
164
165 /* API table for Xcv Monitor functions */
166
167 struct xcv_api_table {
168         const char *name;
169         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
170 };
171
172 static void prune_printername_cache(void);
173
174 /********************************************************************
175  * Canonicalize servername.
176  ********************************************************************/
177
178 static const char *canon_servername(const char *servername)
179 {
180         const char *pservername = servername;
181         while (*pservername == '\\') {
182                 pservername++;
183         }
184         return pservername;
185 }
186
187 /* translate between internal status numbers and NT status numbers */
188 static int nt_printj_status(int v)
189 {
190         switch (v) {
191         case LPQ_QUEUED:
192                 return 0;
193         case LPQ_PAUSED:
194                 return JOB_STATUS_PAUSED;
195         case LPQ_SPOOLING:
196                 return JOB_STATUS_SPOOLING;
197         case LPQ_PRINTING:
198                 return JOB_STATUS_PRINTING;
199         case LPQ_ERROR:
200                 return JOB_STATUS_ERROR;
201         case LPQ_DELETING:
202                 return JOB_STATUS_DELETING;
203         case LPQ_OFFLINE:
204                 return JOB_STATUS_OFFLINE;
205         case LPQ_PAPEROUT:
206                 return JOB_STATUS_PAPEROUT;
207         case LPQ_PRINTED:
208                 return JOB_STATUS_PRINTED;
209         case LPQ_DELETED:
210                 return JOB_STATUS_DELETED;
211         case LPQ_BLOCKED:
212                 return JOB_STATUS_BLOCKED_DEVQ;
213         case LPQ_USER_INTERVENTION:
214                 return JOB_STATUS_USER_INTERVENTION;
215         }
216         return 0;
217 }
218
219 static int nt_printq_status(int v)
220 {
221         switch (v) {
222         case LPQ_PAUSED:
223                 return PRINTER_STATUS_PAUSED;
224         case LPQ_QUEUED:
225         case LPQ_SPOOLING:
226         case LPQ_PRINTING:
227                 return 0;
228         }
229         return 0;
230 }
231
232 /***************************************************************************
233  Disconnect from the client
234 ****************************************************************************/
235
236 static void srv_spoolss_replycloseprinter(int snum,
237                                           struct printer_handle *prn_hnd)
238 {
239         WERROR result;
240         NTSTATUS status;
241
242         /*
243          * Tell the specific printing tdb we no longer want messages for this printer
244          * by deregistering our PID.
245          */
246
247         if (!print_notify_deregister_pid(snum)) {
248                 DEBUG(0, ("Failed to register our pid for printer %s\n",
249                           lp_const_servicename(snum)));
250         }
251
252         /* weird if the test succeeds !!! */
253         if (prn_hnd->notify.cli_chan == NULL ||
254             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
255             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
256             prn_hnd->notify.cli_chan->active_connections == 0) {
257                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
258                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
259                 TALLOC_FREE(prn_hnd->notify.cli_chan);
260                 return;
261         }
262
263         status = dcerpc_spoolss_ReplyClosePrinter(
264                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
265                                         talloc_tos(),
266                                         &prn_hnd->notify.cli_hnd,
267                                         &result);
268         if (!NT_STATUS_IS_OK(status)) {
269                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
270                           nt_errstr(status)));
271                 result = ntstatus_to_werror(status);
272         } else if (!W_ERROR_IS_OK(result)) {
273                 DEBUG(0, ("reply_close_printer failed [%s].\n",
274                           win_errstr(result)));
275         }
276
277         /* if it's the last connection, deconnect the IPC$ share */
278         if (prn_hnd->notify.cli_chan->active_connections == 1) {
279
280                 cli_shutdown(prn_hnd->notify.cli_chan->cli);
281                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
282                 TALLOC_FREE(prn_hnd->notify.cli_chan);
283
284                 if (prn_hnd->notify.msg_ctx != NULL) {
285                         messaging_deregister(prn_hnd->notify.msg_ctx,
286                                              MSG_PRINTER_NOTIFY2, NULL);
287                 }
288         }
289
290         if (prn_hnd->notify.cli_chan) {
291                 prn_hnd->notify.cli_chan->active_connections--;
292                 prn_hnd->notify.cli_chan = NULL;
293         }
294 }
295
296 /****************************************************************************
297  Functions to free a printer entry datastruct.
298 ****************************************************************************/
299
300 static int printer_entry_destructor(struct printer_handle *Printer)
301 {
302         if (Printer->notify.cli_chan != NULL &&
303             Printer->notify.cli_chan->active_connections > 0) {
304                 int snum = -1;
305
306                 switch(Printer->printer_type) {
307                 case SPLHND_SERVER:
308                         srv_spoolss_replycloseprinter(snum, Printer);
309                         break;
310
311                 case SPLHND_PRINTER:
312                         snum = print_queue_snum(Printer->sharename);
313                         if (snum != -1) {
314                                 srv_spoolss_replycloseprinter(snum, Printer);
315                         }
316                         break;
317                 default:
318                         break;
319                 }
320         }
321
322         Printer->notify.flags=0;
323         Printer->notify.options=0;
324         Printer->notify.localmachine[0]='\0';
325         Printer->notify.printerlocal=0;
326         TALLOC_FREE(Printer->notify.option);
327         TALLOC_FREE(Printer->devmode);
328
329         /* Remove from the internal list. */
330         DLIST_REMOVE(printers_list, Printer);
331         return 0;
332 }
333
334 /****************************************************************************
335   find printer index by handle
336 ****************************************************************************/
337
338 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
339                                                         struct policy_handle *hnd)
340 {
341         struct printer_handle *find_printer = NULL;
342
343         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
344                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
345                 return NULL;
346         }
347
348         return find_printer;
349 }
350
351 /****************************************************************************
352  Close printer index by handle.
353 ****************************************************************************/
354
355 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
356 {
357         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
358
359         if (!Printer) {
360                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
361                         OUR_HANDLE(hnd)));
362                 return false;
363         }
364
365         close_policy_hnd(p, hnd);
366
367         return true;
368 }
369
370 /****************************************************************************
371  Delete a printer given a handle.
372 ****************************************************************************/
373
374 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
375                                   const char *sharename,
376                                   struct messaging_context *msg_ctx)
377 {
378         char *cmd = lp_deleteprinter_command(talloc_tos());
379         char *command = NULL;
380         int ret;
381         bool is_print_op = false;
382
383         /* can't fail if we don't try */
384
385         if ( !*cmd )
386                 return WERR_OK;
387
388         command = talloc_asprintf(ctx,
389                         "%s \"%s\"",
390                         cmd, sharename);
391         if (!command) {
392                 return WERR_NOMEM;
393         }
394         if ( token )
395                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
396
397         DEBUG(10,("Running [%s]\n", command));
398
399         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
400
401         if ( is_print_op )
402                 become_root();
403
404         if ( (ret = smbrun(command, NULL)) == 0 ) {
405                 /* Tell everyone we updated smb.conf. */
406                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
407         }
408
409         if ( is_print_op )
410                 unbecome_root();
411
412         /********** END SePrintOperatorPrivlege BLOCK **********/
413
414         DEBUGADD(10,("returned [%d]\n", ret));
415
416         TALLOC_FREE(command);
417
418         if (ret != 0)
419                 return WERR_BADFID; /* What to return here? */
420
421         return WERR_OK;
422 }
423
424 /****************************************************************************
425  Delete a printer given a handle.
426 ****************************************************************************/
427
428 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
429 {
430         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
431         WERROR result;
432
433         if (!Printer) {
434                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
435                         OUR_HANDLE(hnd)));
436                 return WERR_BADFID;
437         }
438
439         /*
440          * It turns out that Windows allows delete printer on a handle
441          * opened by an admin user, then used on a pipe handle created
442          * by an anonymous user..... but they're working on security.... riiight !
443          * JRA.
444          */
445
446         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
447                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
448                 return WERR_ACCESS_DENIED;
449         }
450
451         /* this does not need a become root since the access check has been
452            done on the handle already */
453
454         result = winreg_delete_printer_key_internal(p->mem_ctx,
455                                            get_session_info_system(),
456                                            p->msg_ctx,
457                                            Printer->sharename,
458                                            "");
459         if (!W_ERROR_IS_OK(result)) {
460                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
461                 return WERR_BADFID;
462         }
463
464         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
465                                      Printer->sharename, p->msg_ctx);
466         if (!W_ERROR_IS_OK(result)) {
467                 return result;
468         }
469         prune_printername_cache();
470         return WERR_OK;
471 }
472
473 /****************************************************************************
474  Return the snum of a printer corresponding to an handle.
475 ****************************************************************************/
476
477 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
478                              int *number, struct share_params **params)
479 {
480         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
481
482         if (!Printer) {
483                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
484                         OUR_HANDLE(hnd)));
485                 return false;
486         }
487
488         switch (Printer->printer_type) {
489                 case SPLHND_PRINTER:
490                         DEBUG(4,("short name:%s\n", Printer->sharename));
491                         *number = print_queue_snum(Printer->sharename);
492                         return (*number != -1);
493                 case SPLHND_SERVER:
494                         return false;
495                 default:
496                         return false;
497         }
498 }
499
500 /****************************************************************************
501  Set printer handle type.
502  Check if it's \\server or \\server\printer
503 ****************************************************************************/
504
505 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
506 {
507         DEBUG(3,("Setting printer type=%s\n", handlename));
508
509         /* it's a print server */
510         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
511                 DEBUGADD(4,("Printer is a print server\n"));
512                 Printer->printer_type = SPLHND_SERVER;
513         }
514         /* it's a printer (set_printer_hnd_name() will handle port monitors */
515         else {
516                 DEBUGADD(4,("Printer is a printer\n"));
517                 Printer->printer_type = SPLHND_PRINTER;
518         }
519
520         return true;
521 }
522
523 static void prune_printername_cache_fn(const char *key, const char *value,
524                                        time_t timeout, void *private_data)
525 {
526         gencache_del(key);
527 }
528
529 static void prune_printername_cache(void)
530 {
531         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
532 }
533
534 /****************************************************************************
535  Set printer handle name..  Accept names like \\server, \\server\printer,
536  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
537  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
538  XcvDataPort() interface.
539 ****************************************************************************/
540
541 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
542                                    const struct auth_session_info *session_info,
543                                    struct messaging_context *msg_ctx,
544                                    struct printer_handle *Printer,
545                                    const char *handlename)
546 {
547         int snum;
548         int n_services=lp_numservices();
549         char *aprinter;
550         const char *printername;
551         const char *servername = NULL;
552         fstring sname;
553         bool found = false;
554         struct spoolss_PrinterInfo2 *info2 = NULL;
555         WERROR result;
556         char *p;
557
558         /*
559          * Hopefully nobody names his printers like this. Maybe \ or ,
560          * are illegal in printer names even?
561          */
562         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
563         char *cache_key;
564         char *tmp;
565
566         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
567                 (unsigned long)strlen(handlename)));
568
569         aprinter = discard_const_p(char, handlename);
570         if ( *handlename == '\\' ) {
571                 servername = canon_servername(handlename);
572                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
573                         *aprinter = '\0';
574                         aprinter++;
575                 }
576                 if (!is_myname_or_ipaddr(servername)) {
577                         return WERR_INVALID_PRINTER_NAME;
578                 }
579                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
580                 if (Printer->servername == NULL) {
581                         return WERR_NOMEM;
582                 }
583         }
584
585         if (Printer->printer_type == SPLHND_SERVER) {
586                 return WERR_OK;
587         }
588
589         if (Printer->printer_type != SPLHND_PRINTER) {
590                 return WERR_INVALID_HANDLE;
591         }
592
593         DEBUGADD(5, ("searching for [%s]\n", aprinter));
594
595         p = strchr(aprinter, ',');
596         if (p != NULL) {
597                 char *p2 = p;
598                 p++;
599                 if (*p == ' ') {
600                         p++;
601                 }
602                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
603                         *p2 = '\0';
604                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
605                         *p2 = '\0';
606                 }
607         }
608
609         if (p) {
610                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
611         }
612
613         /* check for the Port Monitor Interface */
614         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
615                 Printer->printer_type = SPLHND_PORTMON_TCP;
616                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
617                 found = true;
618         }
619         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
620                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
621                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
622                 found = true;
623         }
624
625         /*
626          * With hundreds of printers, the "for" loop iterating all
627          * shares can be quite expensive, as it is done on every
628          * OpenPrinter. The loop maps "aprinter" to "sname", the
629          * result of which we cache in gencache.
630          */
631
632         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
633                                     aprinter);
634         if ((cache_key != NULL) &&
635             gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
636
637                 found = (strcmp(tmp, printer_not_found) != 0);
638                 if (!found) {
639                         DEBUG(4, ("Printer %s not found\n", aprinter));
640                         TALLOC_FREE(tmp);
641                         return WERR_INVALID_PRINTER_NAME;
642                 }
643                 fstrcpy(sname, tmp);
644                 TALLOC_FREE(tmp);
645         }
646
647         /* Search all sharenames first as this is easier than pulling
648            the printer_info_2 off of disk. Don't use find_service() since
649            that calls out to map_username() */
650
651         /* do another loop to look for printernames */
652         for (snum = 0; !found && snum < n_services; snum++) {
653                 const char *printer = lp_const_servicename(snum);
654
655                 /* no point going on if this is not a printer */
656                 if (!(lp_snum_ok(snum) && lp_printable(snum))) {
657                         continue;
658                 }
659
660                 /* ignore [printers] share */
661                 if (strequal(printer, "printers")) {
662                         continue;
663                 }
664
665                 fstrcpy(sname, printer);
666                 if (strequal(aprinter, printer)) {
667                         found = true;
668                         break;
669                 }
670
671                 /* no point looking up the printer object if
672                    we aren't allowing printername != sharename */
673                 if (lp_force_printername(snum)) {
674                         continue;
675                 }
676
677                 result = winreg_get_printer_internal(mem_ctx,
678                                             session_info,
679                                             msg_ctx,
680                                             sname,
681                                             &info2);
682                 if ( !W_ERROR_IS_OK(result) ) {
683                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
684                                  sname, win_errstr(result)));
685                         continue;
686                 }
687
688                 printername = strrchr(info2->printername, '\\');
689                 if (printername == NULL) {
690                         printername = info2->printername;
691                 } else {
692                         printername++;
693                 }
694
695                 if (strequal(printername, aprinter)) {
696                         found = true;
697                         break;
698                 }
699
700                 DEBUGADD(10, ("printername: %s\n", printername));
701
702                 TALLOC_FREE(info2);
703         }
704
705         if ( !found ) {
706                 if (cache_key != NULL) {
707                         gencache_set(cache_key, printer_not_found,
708                                      time(NULL)+300);
709                         TALLOC_FREE(cache_key);
710                 }
711                 DEBUGADD(4,("Printer not found\n"));
712                 return WERR_INVALID_PRINTER_NAME;
713         }
714
715         if (cache_key != NULL) {
716                 gencache_set(cache_key, sname, time(NULL)+300);
717                 TALLOC_FREE(cache_key);
718         }
719
720         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
721
722         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
723
724         return WERR_OK;
725 }
726
727 /****************************************************************************
728  Find first available printer slot. creates a printer handle for you.
729  ****************************************************************************/
730
731 static WERROR open_printer_hnd(struct pipes_struct *p,
732                                struct policy_handle *hnd,
733                                const char *name,
734                                uint32_t access_granted)
735 {
736         struct printer_handle *new_printer;
737         WERROR result;
738
739         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
740
741         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
742         if (new_printer == NULL) {
743                 return WERR_NOMEM;
744         }
745         talloc_set_destructor(new_printer, printer_entry_destructor);
746
747         /* This also steals the printer_handle on the policy_handle */
748         if (!create_policy_hnd(p, hnd, new_printer)) {
749                 TALLOC_FREE(new_printer);
750                 return WERR_INVALID_HANDLE;
751         }
752
753         /* Add to the internal list. */
754         DLIST_ADD(printers_list, new_printer);
755
756         new_printer->notify.option=NULL;
757
758         if (!set_printer_hnd_printertype(new_printer, name)) {
759                 close_printer_handle(p, hnd);
760                 return WERR_INVALID_HANDLE;
761         }
762
763         result = set_printer_hnd_name(p->mem_ctx,
764                                       get_session_info_system(),
765                                       p->msg_ctx,
766                                       new_printer, name);
767         if (!W_ERROR_IS_OK(result)) {
768                 close_printer_handle(p, hnd);
769                 return result;
770         }
771
772         new_printer->access_granted = access_granted;
773
774         DEBUG(5, ("%d printer handles active\n",
775                   (int)num_pipe_handles(p)));
776
777         return WERR_OK;
778 }
779
780 /***************************************************************************
781  check to see if the client motify handle is monitoring the notification
782  given by (notify_type, notify_field).
783  **************************************************************************/
784
785 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
786                                       uint16_t notify_field)
787 {
788         return true;
789 }
790
791 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
792                                 uint16_t notify_field)
793 {
794         struct spoolss_NotifyOption *option = p->notify.option;
795         uint32_t i, j;
796
797         /*
798          * Flags should always be zero when the change notify
799          * is registered by the client's spooler.  A user Win32 app
800          * might use the flags though instead of the NOTIFY_OPTION_INFO
801          * --jerry
802          */
803
804         if (!option) {
805                 return false;
806         }
807
808         if (p->notify.flags)
809                 return is_monitoring_event_flags(
810                         p->notify.flags, notify_type, notify_field);
811
812         for (i = 0; i < option->count; i++) {
813
814                 /* Check match for notify_type */
815
816                 if (option->types[i].type != notify_type)
817                         continue;
818
819                 /* Check match for field */
820
821                 for (j = 0; j < option->types[i].count; j++) {
822                         if (option->types[i].fields[j].field == notify_field) {
823                                 return true;
824                         }
825                 }
826         }
827
828         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
829                    p->servername, p->sharename, notify_type, notify_field));
830
831         return false;
832 }
833
834 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
835         _data->data.integer[0] = _integer; \
836         _data->data.integer[1] = 0;
837
838
839 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
840         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
841         if (!_data->data.string.string) {\
842                 _data->data.string.size = 0; \
843         } \
844         _data->data.string.size = strlen_m_term(_p) * 2;
845
846 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
847         _data->data.devmode.devmode = _devmode;
848
849 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
850                                    struct tm *t,
851                                    const char **pp,
852                                    uint32_t *plen)
853 {
854         struct spoolss_Time st;
855         uint32_t len = 16;
856         char *p;
857
858         if (!init_systemtime(&st, t)) {
859                 return;
860         }
861
862         p = talloc_array(mem_ctx, char, len);
863         if (!p) {
864                 return;
865         }
866
867         /*
868          * Systemtime must be linearized as a set of UINT16's.
869          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
870          */
871
872         SSVAL(p, 0, st.year);
873         SSVAL(p, 2, st.month);
874         SSVAL(p, 4, st.day_of_week);
875         SSVAL(p, 6, st.day);
876         SSVAL(p, 8, st.hour);
877         SSVAL(p, 10, st.minute);
878         SSVAL(p, 12, st.second);
879         SSVAL(p, 14, st.millisecond);
880
881         *pp = p;
882         *plen = len;
883 }
884
885 /* Convert a notification message to a struct spoolss_Notify */
886
887 static void notify_one_value(struct spoolss_notify_msg *msg,
888                              struct spoolss_Notify *data,
889                              TALLOC_CTX *mem_ctx)
890 {
891         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
892 }
893
894 static void notify_string(struct spoolss_notify_msg *msg,
895                           struct spoolss_Notify *data,
896                           TALLOC_CTX *mem_ctx)
897 {
898         /* The length of the message includes the trailing \0 */
899
900         data->data.string.size = msg->len * 2;
901         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
902         if (!data->data.string.string) {
903                 data->data.string.size = 0;
904                 return;
905         }
906 }
907
908 static void notify_system_time(struct spoolss_notify_msg *msg,
909                                struct spoolss_Notify *data,
910                                TALLOC_CTX *mem_ctx)
911 {
912         data->data.string.string = NULL;
913         data->data.string.size = 0;
914
915         if (msg->len != sizeof(time_t)) {
916                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
917                           msg->len));
918                 return;
919         }
920
921         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
922                                &data->data.string.string,
923                                &data->data.string.size);
924 }
925
926 struct notify2_message_table {
927         const char *name;
928         void (*fn)(struct spoolss_notify_msg *msg,
929                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
930 };
931
932 static struct notify2_message_table printer_notify_table[] = {
933         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
934         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
935         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
936         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
937         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
938         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
939         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
940         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
941         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
942         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
943         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
944         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
945         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
946         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
947         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
948         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
949         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
950         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
951         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
952 };
953
954 static struct notify2_message_table job_notify_table[] = {
955         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
956         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
957         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
958         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
959         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
960         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
961         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
962         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
963         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
964         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
965         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
966         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
967         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
968         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
969         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
970         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
971         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
972         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
973         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
974         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
975         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
976         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
977         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
978         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
979 };
980
981
982 /***********************************************************************
983  Allocate talloc context for container object
984  **********************************************************************/
985
986 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
987 {
988         if ( !ctr )
989                 return;
990
991         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
992
993         return;
994 }
995
996 /***********************************************************************
997  release all allocated memory and zero out structure
998  **********************************************************************/
999
1000 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1001 {
1002         if ( !ctr )
1003                 return;
1004
1005         if ( ctr->ctx )
1006                 talloc_destroy(ctr->ctx);
1007
1008         ZERO_STRUCTP(ctr);
1009
1010         return;
1011 }
1012
1013 /***********************************************************************
1014  **********************************************************************/
1015
1016 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1017 {
1018         if ( !ctr )
1019                 return NULL;
1020
1021         return ctr->ctx;
1022 }
1023
1024 /***********************************************************************
1025  **********************************************************************/
1026
1027 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1028 {
1029         if ( !ctr || !ctr->msg_groups )
1030                 return NULL;
1031
1032         if ( idx >= ctr->num_groups )
1033                 return NULL;
1034
1035         return &ctr->msg_groups[idx];
1036
1037 }
1038
1039 /***********************************************************************
1040  How many groups of change messages do we have ?
1041  **********************************************************************/
1042
1043 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1044 {
1045         if ( !ctr )
1046                 return 0;
1047
1048         return ctr->num_groups;
1049 }
1050
1051 /***********************************************************************
1052  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1053  **********************************************************************/
1054
1055 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1056 {
1057         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1058         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1059         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1060         int                             i, new_slot;
1061
1062         if ( !ctr || !msg )
1063                 return 0;
1064
1065         /* loop over all groups looking for a matching printer name */
1066
1067         for ( i=0; i<ctr->num_groups; i++ ) {
1068                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1069                         break;
1070         }
1071
1072         /* add a new group? */
1073
1074         if ( i == ctr->num_groups ) {
1075                 ctr->num_groups++;
1076
1077                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1078                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1079                         return 0;
1080                 }
1081                 ctr->msg_groups = groups;
1082
1083                 /* clear the new entry and set the printer name */
1084
1085                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1086                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1087         }
1088
1089         /* add the change messages; 'i' is the correct index now regardless */
1090
1091         msg_grp = &ctr->msg_groups[i];
1092
1093         msg_grp->num_msgs++;
1094
1095         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1096                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1097                 return 0;
1098         }
1099         msg_grp->msgs = msg_list;
1100
1101         new_slot = msg_grp->num_msgs-1;
1102         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1103
1104         /* need to allocate own copy of data */
1105
1106         if ( msg->len != 0 )
1107                 msg_grp->msgs[new_slot].notify.data = (char *)
1108                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1109
1110         return ctr->num_groups;
1111 }
1112
1113 static void construct_info_data(struct spoolss_Notify *info_data,
1114                                 enum spoolss_NotifyType type,
1115                                 uint16_t field, int id);
1116
1117 /***********************************************************************
1118  Send a change notication message on all handles which have a call
1119  back registered
1120  **********************************************************************/
1121
1122 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1123                                   struct printer_handle *prn_hnd,
1124                                   SPOOLSS_NOTIFY_MSG *messages,
1125                                   uint32_t num_msgs,
1126                                   struct spoolss_Notify **_notifies,
1127                                   int *_count)
1128 {
1129         struct spoolss_Notify *notifies;
1130         SPOOLSS_NOTIFY_MSG *msg;
1131         int count = 0;
1132         uint32_t id;
1133         int i;
1134
1135         notifies = talloc_zero_array(mem_ctx,
1136                                      struct spoolss_Notify, num_msgs);
1137         if (!notifies) {
1138                 return ENOMEM;
1139         }
1140
1141         for (i = 0; i < num_msgs; i++) {
1142
1143                 msg = &messages[i];
1144
1145                 /* Are we monitoring this event? */
1146
1147                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1148                         continue;
1149                 }
1150
1151                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1152                            "for printer [%s]\n",
1153                            msg->type, msg->field, prn_hnd->sharename));
1154
1155                 /*
1156                  * if the is a printer notification handle and not a job
1157                  * notification type, then set the id to 0.
1158                  * Otherwise just use what was specified in the message.
1159                  *
1160                  * When registering change notification on a print server
1161                  * handle we always need to send back the id (snum) matching
1162                  * the printer for which the change took place.
1163                  * For change notify registered on a printer handle,
1164                  * this does not matter and the id should be 0.
1165                  *
1166                  * --jerry
1167                  */
1168
1169                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1170                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1171                         id = 0;
1172                 } else {
1173                         id = msg->id;
1174                 }
1175
1176                 /* Convert unix jobid to smb jobid */
1177
1178                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1179                         id = sysjob_to_jobid(msg->id);
1180
1181                         if (id == -1) {
1182                                 DEBUG(3, ("no such unix jobid %d\n",
1183                                           msg->id));
1184                                 continue;
1185                         }
1186                 }
1187
1188                 construct_info_data(&notifies[count],
1189                                     msg->type, msg->field, id);
1190
1191                 switch(msg->type) {
1192                 case PRINTER_NOTIFY_TYPE:
1193                         if (printer_notify_table[msg->field].fn) {
1194                                 printer_notify_table[msg->field].fn(msg,
1195                                                 &notifies[count], mem_ctx);
1196                         }
1197                         break;
1198
1199                 case JOB_NOTIFY_TYPE:
1200                         if (job_notify_table[msg->field].fn) {
1201                                 job_notify_table[msg->field].fn(msg,
1202                                                 &notifies[count], mem_ctx);
1203                         }
1204                         break;
1205
1206                 default:
1207                         DEBUG(5, ("Unknown notification type %d\n",
1208                                   msg->type));
1209                         continue;
1210                 }
1211
1212                 count++;
1213         }
1214
1215         *_notifies = notifies;
1216         *_count = count;
1217
1218         return 0;
1219 }
1220
1221 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1222                                 struct printer_handle *prn_hnd,
1223                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1224 {
1225         struct spoolss_Notify *notifies;
1226         int count = 0;
1227         union spoolss_ReplyPrinterInfo info;
1228         struct spoolss_NotifyInfo info0;
1229         uint32_t reply_result;
1230         NTSTATUS status;
1231         WERROR werr;
1232         int ret;
1233
1234         /* Is there notification on this handle? */
1235         if (prn_hnd->notify.cli_chan == NULL ||
1236             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1237             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1238             prn_hnd->notify.cli_chan->active_connections == 0) {
1239                 return 0;
1240         }
1241
1242         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1243                    prn_hnd->servername, prn_hnd->sharename));
1244
1245         /* For this printer? Print servers always receive notifications. */
1246         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1247             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1248                 return 0;
1249         }
1250
1251         DEBUG(10,("Our printer\n"));
1252
1253         /* build the array of change notifications */
1254         ret = build_notify2_messages(mem_ctx, prn_hnd,
1255                                      msg_group->msgs,
1256                                      msg_group->num_msgs,
1257                                      &notifies, &count);
1258         if (ret) {
1259                 return ret;
1260         }
1261
1262         info0.version   = 0x2;
1263         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1264         info0.count     = count;
1265         info0.notifies  = notifies;
1266
1267         info.info0 = &info0;
1268
1269         status = dcerpc_spoolss_RouterReplyPrinterEx(
1270                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1271                                 mem_ctx,
1272                                 &prn_hnd->notify.cli_hnd,
1273                                 prn_hnd->notify.change, /* color */
1274                                 prn_hnd->notify.flags,
1275                                 &reply_result,
1276                                 0, /* reply_type, must be 0 */
1277                                 info, &werr);
1278         if (!NT_STATUS_IS_OK(status)) {
1279                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1280                           "failed: %s\n",
1281                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1282                           nt_errstr(status)));
1283                 werr = ntstatus_to_werror(status);
1284         } else if (!W_ERROR_IS_OK(werr)) {
1285                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1286                           "failed: %s\n",
1287                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1288                           win_errstr(werr)));
1289         }
1290         switch (reply_result) {
1291         case 0:
1292                 break;
1293         case PRINTER_NOTIFY_INFO_DISCARDED:
1294         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1295         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1296                 break;
1297         default:
1298                 break;
1299         }
1300
1301         return 0;
1302 }
1303
1304 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1305 {
1306         struct printer_handle    *p;
1307         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1308         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1309         int ret;
1310
1311         if ( !msg_group ) {
1312                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1313                 return;
1314         }
1315
1316         if (!msg_group->msgs) {
1317                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1318                 return;
1319         }
1320
1321         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1322
1323         /* loop over all printers */
1324
1325         for (p = printers_list; p; p = p->next) {
1326                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1327                 if (ret) {
1328                         goto done;
1329                 }
1330         }
1331
1332 done:
1333         DEBUG(8,("send_notify2_changes: Exit...\n"));
1334         return;
1335 }
1336
1337 /***********************************************************************
1338  **********************************************************************/
1339
1340 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1341 {
1342
1343         uint32_t tv_sec, tv_usec;
1344         size_t offset = 0;
1345
1346         /* Unpack message */
1347
1348         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1349                              msg->printer);
1350
1351         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1352                                 &tv_sec, &tv_usec,
1353                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1354
1355         if (msg->len == 0)
1356                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1357                            &msg->notify.value[0], &msg->notify.value[1]);
1358         else
1359                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1360                            &msg->len, &msg->notify.data);
1361
1362         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1363                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1364
1365         tv->tv_sec = tv_sec;
1366         tv->tv_usec = tv_usec;
1367
1368         if (msg->len == 0)
1369                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1370                           msg->notify.value[1]));
1371         else
1372                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1373
1374         return true;
1375 }
1376
1377 /********************************************************************
1378  Receive a notify2 message list
1379  ********************************************************************/
1380
1381 static void receive_notify2_message_list(struct messaging_context *msg,
1382                                          void *private_data,
1383                                          uint32_t msg_type,
1384                                          struct server_id server_id,
1385                                          DATA_BLOB *data)
1386 {
1387         size_t                  msg_count, i;
1388         char                    *buf = (char *)data->data;
1389         char                    *msg_ptr;
1390         size_t                  msg_len;
1391         SPOOLSS_NOTIFY_MSG      notify;
1392         SPOOLSS_NOTIFY_MSG_CTR  messages;
1393         int                     num_groups;
1394
1395         if (data->length < 4) {
1396                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1397                 return;
1398         }
1399
1400         msg_count = IVAL(buf, 0);
1401         msg_ptr = buf + 4;
1402
1403         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1404
1405         if (msg_count == 0) {
1406                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1407                 return;
1408         }
1409
1410         /* initialize the container */
1411
1412         ZERO_STRUCT( messages );
1413         notify_msg_ctr_init( &messages );
1414
1415         /*
1416          * build message groups for each printer identified
1417          * in a change_notify msg.  Remember that a PCN message
1418          * includes the handle returned for the srv_spoolss_replyopenprinter()
1419          * call.  Therefore messages are grouped according to printer handle.
1420          */
1421
1422         for ( i=0; i<msg_count; i++ ) {
1423                 struct timeval msg_tv;
1424
1425                 if (msg_ptr + 4 - buf > data->length) {
1426                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1427                         return;
1428                 }
1429
1430                 msg_len = IVAL(msg_ptr,0);
1431                 msg_ptr += 4;
1432
1433                 if (msg_ptr + msg_len - buf > data->length) {
1434                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1435                         return;
1436                 }
1437
1438                 /* unpack messages */
1439
1440                 ZERO_STRUCT( notify );
1441                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1442                 msg_ptr += msg_len;
1443
1444                 /* add to correct list in container */
1445
1446                 notify_msg_ctr_addmsg( &messages, &notify );
1447
1448                 /* free memory that might have been allocated by notify2_unpack_msg() */
1449
1450                 if ( notify.len != 0 )
1451                         SAFE_FREE( notify.notify.data );
1452         }
1453
1454         /* process each group of messages */
1455
1456         num_groups = notify_msg_ctr_numgroups( &messages );
1457         for ( i=0; i<num_groups; i++ )
1458                 send_notify2_changes( &messages, i );
1459
1460
1461         /* cleanup */
1462
1463         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1464                 (uint32_t)msg_count ));
1465
1466         notify_msg_ctr_destroy( &messages );
1467
1468         return;
1469 }
1470
1471 /********************************************************************
1472  Send a message to ourself about new driver being installed
1473  so we can upgrade the information for each printer bound to this
1474  driver
1475  ********************************************************************/
1476
1477 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1478                                             struct messaging_context *msg_ctx)
1479 {
1480         int len = strlen(drivername);
1481
1482         if (!len)
1483                 return false;
1484
1485         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1486                 drivername));
1487
1488         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1489                            MSG_PRINTER_DRVUPGRADE,
1490                            (const uint8_t *)drivername, len+1);
1491
1492         return true;
1493 }
1494
1495 void srv_spoolss_cleanup(void)
1496 {
1497         struct printer_session_counter *session_counter;
1498
1499         for (session_counter = counter_list;
1500              session_counter != NULL;
1501              session_counter = counter_list) {
1502                 DLIST_REMOVE(counter_list, session_counter);
1503                 TALLOC_FREE(session_counter);
1504         }
1505 }
1506
1507 /**********************************************************************
1508  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1509  over all printers, upgrading ones as necessary
1510  This is now *ONLY* called inside the background lpq updater. JRA.
1511  **********************************************************************/
1512
1513 void do_drv_upgrade_printer(struct messaging_context *msg,
1514                             void *private_data,
1515                             uint32_t msg_type,
1516                             struct server_id server_id,
1517                             DATA_BLOB *data)
1518 {
1519         TALLOC_CTX *tmp_ctx;
1520         const struct auth_session_info *session_info = get_session_info_system();
1521         struct spoolss_PrinterInfo2 *pinfo2;
1522         WERROR result;
1523         const char *drivername;
1524         int snum;
1525         int n_services = lp_numservices();
1526         struct dcerpc_binding_handle *b = NULL;
1527
1528         tmp_ctx = talloc_new(NULL);
1529         if (!tmp_ctx) return;
1530
1531         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1532         if (!drivername) {
1533                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1534                 goto done;
1535         }
1536
1537         DEBUG(10, ("do_drv_upgrade_printer: "
1538                    "Got message for new driver [%s]\n", drivername));
1539
1540         /* Iterate the printer list */
1541
1542         for (snum = 0; snum < n_services; snum++) {
1543                 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1544                         continue;
1545                 }
1546
1547                 /* ignore [printers] share */
1548                 if (strequal(lp_const_servicename(snum), "printers")) {
1549                         continue;
1550                 }
1551
1552                 if (b == NULL) {
1553                         result = winreg_printer_binding_handle(tmp_ctx,
1554                                                                session_info,
1555                                                                msg,
1556                                                                &b);
1557                         if (!W_ERROR_IS_OK(result)) {
1558                                 break;
1559                         }
1560                 }
1561
1562                 result = winreg_get_printer(tmp_ctx, b,
1563                                             lp_const_servicename(snum),
1564                                             &pinfo2);
1565
1566                 if (!W_ERROR_IS_OK(result)) {
1567                         continue;
1568                 }
1569
1570                 if (!pinfo2->drivername) {
1571                         continue;
1572                 }
1573
1574                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1575                         continue;
1576                 }
1577
1578                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1579
1580                 /* all we care about currently is the change_id */
1581                 result = winreg_printer_update_changeid(tmp_ctx, b,
1582                                                         pinfo2->printername);
1583
1584                 if (!W_ERROR_IS_OK(result)) {
1585                         DEBUG(3, ("do_drv_upgrade_printer: "
1586                                   "Failed to update changeid [%s]\n",
1587                                   win_errstr(result)));
1588                 }
1589         }
1590
1591         /* all done */
1592 done:
1593         talloc_free(tmp_ctx);
1594 }
1595
1596 /********************************************************************
1597  Update the cache for all printq's with a registered client
1598  connection
1599  ********************************************************************/
1600
1601 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1602 {
1603         struct printer_handle *printer = printers_list;
1604         int snum;
1605
1606         /* loop through all printers and update the cache where
1607            a client is connected */
1608         while (printer) {
1609                 if ((printer->printer_type == SPLHND_PRINTER) &&
1610                     ((printer->notify.cli_chan != NULL) &&
1611                      (printer->notify.cli_chan->active_connections > 0))) {
1612                         snum = print_queue_snum(printer->sharename);
1613                         print_queue_status(msg_ctx, snum, NULL, NULL);
1614                 }
1615
1616                 printer = printer->next;
1617         }
1618
1619         return;
1620 }
1621
1622 /****************************************************************
1623  _spoolss_OpenPrinter
1624 ****************************************************************/
1625
1626 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1627                             struct spoolss_OpenPrinter *r)
1628 {
1629         struct spoolss_OpenPrinterEx e;
1630         struct spoolss_UserLevel1 level1;
1631         WERROR werr;
1632
1633         ZERO_STRUCT(level1);
1634
1635         e.in.printername        = r->in.printername;
1636         e.in.datatype           = r->in.datatype;
1637         e.in.devmode_ctr        = r->in.devmode_ctr;
1638         e.in.access_mask        = r->in.access_mask;
1639         e.in.userlevel_ctr.level                = 1;
1640         e.in.userlevel_ctr.user_info.level1     = &level1;
1641
1642         e.out.handle            = r->out.handle;
1643
1644         werr = _spoolss_OpenPrinterEx(p, &e);
1645
1646         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1647                 /* OpenPrinterEx returns this for a bad
1648                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1649                  * instead.
1650                  */
1651                 werr = WERR_INVALID_PRINTER_NAME;
1652         }
1653
1654         return werr;
1655 }
1656
1657 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1658                               struct spoolss_DeviceMode *orig,
1659                               struct spoolss_DeviceMode **dest)
1660 {
1661         struct spoolss_DeviceMode *dm;
1662
1663         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1664         if (!dm) {
1665                 return WERR_NOMEM;
1666         }
1667
1668         /* copy all values, then duplicate strings and structs */
1669         *dm = *orig;
1670
1671         dm->devicename = talloc_strdup(dm, orig->devicename);
1672         if (!dm->devicename) {
1673                 return WERR_NOMEM;
1674         }
1675         dm->formname = talloc_strdup(dm, orig->formname);
1676         if (!dm->formname) {
1677                 return WERR_NOMEM;
1678         }
1679         if (orig->driverextra_data.data) {
1680                 dm->driverextra_data.data =
1681                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1682                                         orig->driverextra_data.length);
1683                 if (!dm->driverextra_data.data) {
1684                         return WERR_NOMEM;
1685                 }
1686         }
1687
1688         *dest = dm;
1689         return WERR_OK;
1690 }
1691
1692 /****************************************************************
1693  _spoolss_OpenPrinterEx
1694 ****************************************************************/
1695
1696 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1697                               struct spoolss_OpenPrinterEx *r)
1698 {
1699         int snum;
1700         char *raddr;
1701         char *rhost;
1702         struct printer_handle *Printer=NULL;
1703         WERROR result;
1704         int rc;
1705
1706         if (!r->in.printername) {
1707                 return WERR_INVALID_PARAM;
1708         }
1709
1710         if (!*r->in.printername) {
1711                 return WERR_INVALID_PARAM;
1712         }
1713
1714         if (r->in.userlevel_ctr.level > 3) {
1715                 return WERR_INVALID_PARAM;
1716         }
1717         if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1718             (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1719             (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1720                 return WERR_INVALID_PARAM;
1721         }
1722
1723         /*
1724          * The printcap printer share inventory is updated on client
1725          * enumeration. For clients that do not perform enumeration prior to
1726          * access, such as cupssmbadd, we reinitialise the printer share
1727          * inventory on open as well.
1728          */
1729         become_root();
1730         delete_and_reload_printers(server_event_context(), p->msg_ctx);
1731         unbecome_root();
1732
1733         /* some sanity check because you can open a printer or a print server */
1734         /* aka: \\server\printer or \\server */
1735
1736         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1737
1738         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1739         if (!W_ERROR_IS_OK(result)) {
1740                 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1741                         "for printer %s\n", r->in.printername));
1742                 ZERO_STRUCTP(r->out.handle);
1743                 return result;
1744         }
1745
1746         Printer = find_printer_index_by_hnd(p, r->out.handle);
1747         if ( !Printer ) {
1748                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1749                         "handle we created for printer %s\n", r->in.printername));
1750                 close_printer_handle(p, r->out.handle);
1751                 ZERO_STRUCTP(r->out.handle);
1752                 return WERR_INVALID_PARAM;
1753         }
1754
1755         /*
1756          * First case: the user is opening the print server:
1757          *
1758          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1759          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1760          *
1761          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1762          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1763          * or if the user is listed in the smb.conf printer admin parameter.
1764          *
1765          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1766          * client view printer folder, but does not show the MSAPW.
1767          *
1768          * Note: this test needs code to check access rights here too. Jeremy
1769          * could you look at this?
1770          *
1771          * Second case: the user is opening a printer:
1772          * NT doesn't let us connect to a printer if the connecting user
1773          * doesn't have print permission.
1774          *
1775          * Third case: user is opening a Port Monitor
1776          * access checks same as opening a handle to the print server.
1777          */
1778
1779         switch (Printer->printer_type )
1780         {
1781         case SPLHND_SERVER:
1782         case SPLHND_PORTMON_TCP:
1783         case SPLHND_PORTMON_LOCAL:
1784                 /* Printserver handles use global struct... */
1785
1786                 snum = -1;
1787
1788                 /* Map standard access rights to object specific access rights */
1789
1790                 se_map_standard(&r->in.access_mask,
1791                                 &printserver_std_mapping);
1792
1793                 /* Deny any object specific bits that don't apply to print
1794                    servers (i.e printer and job specific bits) */
1795
1796                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1797
1798                 if (r->in.access_mask &
1799                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1800                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1801                         close_printer_handle(p, r->out.handle);
1802                         ZERO_STRUCTP(r->out.handle);
1803                         return WERR_ACCESS_DENIED;
1804                 }
1805
1806                 /* Allow admin access */
1807
1808                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1809                 {
1810                         if (!lp_show_add_printer_wizard()) {
1811                                 close_printer_handle(p, r->out.handle);
1812                                 ZERO_STRUCTP(r->out.handle);
1813                                 return WERR_ACCESS_DENIED;
1814                         }
1815
1816                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1817                            and not a printer admin, then fail */
1818
1819                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1820                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1821                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1822                                                 p->session_info->security_token)) {
1823                                 close_printer_handle(p, r->out.handle);
1824                                 ZERO_STRUCTP(r->out.handle);
1825                                 DEBUG(3,("access DENIED as user is not root, "
1826                                         "has no printoperator privilege, "
1827                                         "not a member of the printoperator builtin group and "
1828                                         "is not in printer admin list"));
1829                                 return WERR_ACCESS_DENIED;
1830                         }
1831
1832                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1833                 }
1834                 else
1835                 {
1836                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1837                 }
1838
1839                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1840                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1841
1842                 /* We fall through to return WERR_OK */
1843                 break;
1844
1845         case SPLHND_PRINTER:
1846                 /* NT doesn't let us connect to a printer if the connecting user
1847                    doesn't have print permission.  */
1848
1849                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1850                         close_printer_handle(p, r->out.handle);
1851                         ZERO_STRUCTP(r->out.handle);
1852                         return WERR_BADFID;
1853                 }
1854
1855                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1856                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1857                 }
1858
1859                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1860
1861                 /* map an empty access mask to the minimum access mask */
1862                 if (r->in.access_mask == 0x0)
1863                         r->in.access_mask = PRINTER_ACCESS_USE;
1864
1865                 /*
1866                  * If we are not serving the printer driver for this printer,
1867                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1868                  * will keep NT clients happy  --jerry
1869                  */
1870
1871                 if (lp_use_client_driver(snum)
1872                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1873                 {
1874                         r->in.access_mask = PRINTER_ACCESS_USE;
1875                 }
1876
1877                 /* check smb.conf parameters and the the sec_desc */
1878                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1879                                                          p->mem_ctx);
1880                 if (raddr == NULL) {
1881                         return WERR_NOMEM;
1882                 }
1883
1884                 rc = get_remote_hostname(p->remote_address,
1885                                          &rhost,
1886                                          p->mem_ctx);
1887                 if (rc < 0) {
1888                         return WERR_NOMEM;
1889                 }
1890                 if (strequal(rhost, "UNKNOWN")) {
1891                         rhost = raddr;
1892                 }
1893
1894                 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1895                                   rhost, raddr)) {
1896                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1897                         ZERO_STRUCTP(r->out.handle);
1898                         return WERR_ACCESS_DENIED;
1899                 }
1900
1901                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1902                                    p->session_info->security_token, snum) ||
1903                     !W_ERROR_IS_OK(print_access_check(p->session_info,
1904                                                       p->msg_ctx,
1905                                                       snum,
1906                                                       r->in.access_mask))) {
1907                         DEBUG(3, ("access DENIED for printer open\n"));
1908                         close_printer_handle(p, r->out.handle);
1909                         ZERO_STRUCTP(r->out.handle);
1910                         return WERR_ACCESS_DENIED;
1911                 }
1912
1913                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1914                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1915                         close_printer_handle(p, r->out.handle);
1916                         ZERO_STRUCTP(r->out.handle);
1917                         return WERR_ACCESS_DENIED;
1918                 }
1919
1920                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1921                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1922                 else
1923                         r->in.access_mask = PRINTER_ACCESS_USE;
1924
1925                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1926                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1927
1928                 winreg_create_printer_internal(p->mem_ctx,
1929                                       get_session_info_system(),
1930                                       p->msg_ctx,
1931                                       lp_const_servicename(snum));
1932
1933                 break;
1934
1935         default:
1936                 /* sanity check to prevent programmer error */
1937                 ZERO_STRUCTP(r->out.handle);
1938                 return WERR_BADFID;
1939         }
1940
1941         Printer->access_granted = r->in.access_mask;
1942
1943         /*
1944          * If the client sent a devmode in the OpenPrinter() call, then
1945          * save it here in case we get a job submission on this handle
1946          */
1947
1948          if ((Printer->printer_type != SPLHND_SERVER)
1949           && (r->in.devmode_ctr.devmode != NULL)) {
1950                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1951                                 &Printer->devmode);
1952          }
1953
1954         return WERR_OK;
1955 }
1956
1957 /****************************************************************
1958  _spoolss_ClosePrinter
1959 ****************************************************************/
1960
1961 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1962                              struct spoolss_ClosePrinter *r)
1963 {
1964         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1965
1966         if (Printer && Printer->document_started) {
1967                 struct spoolss_EndDocPrinter e;
1968
1969                 e.in.handle = r->in.handle;
1970
1971                 _spoolss_EndDocPrinter(p, &e);
1972         }
1973
1974         if (!close_printer_handle(p, r->in.handle))
1975                 return WERR_BADFID;
1976
1977         /* clear the returned printer handle.  Observed behavior
1978            from Win2k server.  Don't think this really matters.
1979            Previous code just copied the value of the closed
1980            handle.    --jerry */
1981
1982         ZERO_STRUCTP(r->out.handle);
1983
1984         return WERR_OK;
1985 }
1986
1987 /****************************************************************
1988  _spoolss_DeletePrinter
1989 ****************************************************************/
1990
1991 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1992                               struct spoolss_DeletePrinter *r)
1993 {
1994         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1995         WERROR result;
1996         int snum;
1997
1998         if (Printer && Printer->document_started) {
1999                 struct spoolss_EndDocPrinter e;
2000
2001                 e.in.handle = r->in.handle;
2002
2003                 _spoolss_EndDocPrinter(p, &e);
2004         }
2005
2006         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2007                 winreg_delete_printer_key_internal(p->mem_ctx,
2008                                           get_session_info_system(),
2009                                           p->msg_ctx,
2010                                           lp_const_servicename(snum),
2011                                           "");
2012         }
2013
2014         result = delete_printer_handle(p, r->in.handle);
2015
2016         return result;
2017 }
2018
2019 /*******************************************************************
2020  * static function to lookup the version id corresponding to an
2021  * long architecture string
2022  ******************************************************************/
2023
2024 static const struct print_architecture_table_node archi_table[]= {
2025
2026         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2027         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2028         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2029         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2030         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2031         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2032         {"Windows x64",          SPL_ARCH_X64,          3 },
2033         {NULL,                   "",            -1 }
2034 };
2035
2036 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2037                                    SPOOLSS_DRIVER_VERSION_NT35,
2038                                    SPOOLSS_DRIVER_VERSION_NT4,
2039                                    SPOOLSS_DRIVER_VERSION_200X,
2040                                    -1};
2041
2042 static int get_version_id(const char *arch)
2043 {
2044         int i;
2045
2046         for (i=0; archi_table[i].long_archi != NULL; i++)
2047         {
2048                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2049                         return (archi_table[i].version);
2050         }
2051
2052         return -1;
2053 }
2054
2055 /****************************************************************
2056  _spoolss_DeletePrinterDriver
2057 ****************************************************************/
2058
2059 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2060                                     struct spoolss_DeletePrinterDriver *r)
2061 {
2062
2063         struct spoolss_DriverInfo8 *info = NULL;
2064         int                             version;
2065         WERROR                          status;
2066         struct dcerpc_binding_handle *b;
2067         TALLOC_CTX *tmp_ctx = NULL;
2068         int i;
2069         bool found;
2070
2071         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2072            and not a printer admin, then fail */
2073
2074         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2075             !security_token_has_privilege(p->session_info->security_token,
2076                                           SEC_PRIV_PRINT_OPERATOR)) {
2077                 return WERR_ACCESS_DENIED;
2078         }
2079
2080         /* check that we have a valid driver name first */
2081
2082         if ((version = get_version_id(r->in.architecture)) == -1) {
2083                 return WERR_INVALID_ENVIRONMENT;
2084         }
2085
2086         tmp_ctx = talloc_new(p->mem_ctx);
2087         if (!tmp_ctx) {
2088                 return WERR_NOMEM;
2089         }
2090
2091         status = winreg_printer_binding_handle(tmp_ctx,
2092                                                get_session_info_system(),
2093                                                p->msg_ctx,
2094                                                &b);
2095         if (!W_ERROR_IS_OK(status)) {
2096                 goto done;
2097         }
2098
2099         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2100                 status = winreg_get_driver(tmp_ctx, b,
2101                                            r->in.architecture, r->in.driver,
2102                                            drv_cversion[i], &info);
2103                 if (!W_ERROR_IS_OK(status)) {
2104                         DEBUG(5, ("skipping del of driver with version %d\n",
2105                                   drv_cversion[i]));
2106                         continue;
2107                 }
2108                 found = true;
2109
2110                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2111                         status = WERR_PRINTER_DRIVER_IN_USE;
2112                         goto done;
2113                 }
2114
2115                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2116                 if (!W_ERROR_IS_OK(status)) {
2117                         DEBUG(0, ("failed del of driver with version %d\n",
2118                                   drv_cversion[i]));
2119                         goto done;
2120                 }
2121         }
2122         if (found == false) {
2123                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2124                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2125         } else {
2126                 status = WERR_OK;
2127         }
2128
2129 done:
2130         talloc_free(tmp_ctx);
2131
2132         return status;
2133 }
2134
2135 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2136                                   struct pipes_struct *p,
2137                                   struct spoolss_DeletePrinterDriverEx *r,
2138                                   struct dcerpc_binding_handle *b,
2139                                   struct spoolss_DriverInfo8 *info)
2140 {
2141         WERROR status;
2142         bool delete_files;
2143
2144         if (printer_driver_in_use(mem_ctx, b, info)) {
2145                 status = WERR_PRINTER_DRIVER_IN_USE;
2146                 goto done;
2147         }
2148
2149         /*
2150          * we have a couple of cases to consider.
2151          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2152          *     then the delete should fail if **any** files overlap with
2153          *     other drivers
2154          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2155          *     non-overlapping files
2156          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2157          *     are set, then do not delete any files
2158          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2159          */
2160
2161         delete_files = r->in.delete_flags
2162                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2163
2164
2165         if (delete_files) {
2166                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2167                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2168                         status = WERR_PRINTER_DRIVER_IN_USE;
2169                         goto done;
2170                 }
2171                 /*
2172                  * printer_driver_files_in_use() has trimmed overlapping files
2173                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2174                  */
2175         }
2176
2177
2178         status = winreg_del_driver(mem_ctx, b, info, info->version);
2179         if (!W_ERROR_IS_OK(status)) {
2180                 goto done;
2181         }
2182
2183         /*
2184          * now delete any associated files if delete_files is
2185          * true. Even if this part failes, we return succes
2186          * because the driver doesn not exist any more
2187          */
2188         if (delete_files) {
2189                 delete_driver_files(p->session_info, info);
2190         }
2191
2192 done:
2193         return status;
2194 }
2195
2196 /****************************************************************
2197  _spoolss_DeletePrinterDriverEx
2198 ****************************************************************/
2199
2200 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2201                                       struct spoolss_DeletePrinterDriverEx *r)
2202 {
2203         struct spoolss_DriverInfo8 *info = NULL;
2204         WERROR                          status;
2205         struct dcerpc_binding_handle *b;
2206         TALLOC_CTX *tmp_ctx = NULL;
2207         int i;
2208         bool found;
2209
2210         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2211            and not a printer admin, then fail */
2212
2213         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2214             !security_token_has_privilege(p->session_info->security_token,
2215                                           SEC_PRIV_PRINT_OPERATOR)) {
2216                 return WERR_ACCESS_DENIED;
2217         }
2218
2219         /* check that we have a valid driver name first */
2220         if (get_version_id(r->in.architecture) == -1) {
2221                 /* this is what NT returns */
2222                 return WERR_INVALID_ENVIRONMENT;
2223         }
2224
2225         tmp_ctx = talloc_new(p->mem_ctx);
2226         if (!tmp_ctx) {
2227                 return WERR_NOMEM;
2228         }
2229
2230         status = winreg_printer_binding_handle(tmp_ctx,
2231                                                get_session_info_system(),
2232                                                p->msg_ctx,
2233                                                &b);
2234         if (!W_ERROR_IS_OK(status)) {
2235                 goto done;
2236         }
2237
2238         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2239                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2240                  && (drv_cversion[i] != r->in.version)) {
2241                         continue;
2242                 }
2243
2244                 /* check if a driver with this version exists before delete */
2245                 status = winreg_get_driver(tmp_ctx, b,
2246                                            r->in.architecture, r->in.driver,
2247                                            drv_cversion[i], &info);
2248                 if (!W_ERROR_IS_OK(status)) {
2249                         DEBUG(5, ("skipping del of driver with version %d\n",
2250                                   drv_cversion[i]));
2251                         continue;
2252                 }
2253                 found = true;
2254
2255                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2256                 if (!W_ERROR_IS_OK(status)) {
2257                         DEBUG(0, ("failed to delete driver with version %d\n",
2258                                   drv_cversion[i]));
2259                         goto done;
2260                 }
2261         }
2262         if (found == false) {
2263                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2264                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2265         } else {
2266                 status = WERR_OK;
2267         }
2268
2269 done:
2270         talloc_free(tmp_ctx);
2271         return status;
2272 }
2273
2274
2275 /********************************************************************
2276  GetPrinterData on a printer server Handle.
2277 ********************************************************************/
2278
2279 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2280                                             const char *value,
2281                                             enum winreg_Type *type,
2282                                             union spoolss_PrinterData *data)
2283 {
2284         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2285
2286         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2287                 *type = REG_DWORD;
2288                 SIVAL(&data->value, 0, 0x00);
2289                 return WERR_OK;
2290         }
2291
2292         if (!strcasecmp_m(value, "BeepEnabled")) {
2293                 *type = REG_DWORD;
2294                 SIVAL(&data->value, 0, 0x00);
2295                 return WERR_OK;
2296         }
2297
2298         if (!strcasecmp_m(value, "EventLog")) {
2299                 *type = REG_DWORD;
2300                 /* formally was 0x1b */
2301                 SIVAL(&data->value, 0, 0x00);
2302                 return WERR_OK;
2303         }
2304
2305         if (!strcasecmp_m(value, "NetPopup")) {
2306                 *type = REG_DWORD;
2307                 SIVAL(&data->value, 0, 0x00);
2308                 return WERR_OK;
2309         }
2310
2311         if (!strcasecmp_m(value, "MajorVersion")) {
2312                 *type = REG_DWORD;
2313
2314                 /* Windows NT 4.0 seems to not allow uploading of drivers
2315                    to a server that reports 0x3 as the MajorVersion.
2316                    need to investigate more how Win2k gets around this .
2317                    -- jerry */
2318
2319                 if (RA_WINNT == get_remote_arch()) {
2320                         SIVAL(&data->value, 0, 0x02);
2321                 } else {
2322                         SIVAL(&data->value, 0, 0x03);
2323                 }
2324
2325                 return WERR_OK;
2326         }
2327
2328         if (!strcasecmp_m(value, "MinorVersion")) {
2329                 *type = REG_DWORD;
2330                 SIVAL(&data->value, 0, 0x00);
2331                 return WERR_OK;
2332         }
2333
2334         /* REG_BINARY
2335          *  uint32_t size        = 0x114
2336          *  uint32_t major       = 5
2337          *  uint32_t minor       = [0|1]
2338          *  uint32_t build       = [2195|2600]
2339          *  extra unicode string = e.g. "Service Pack 3"
2340          */
2341         if (!strcasecmp_m(value, "OSVersion")) {
2342                 DATA_BLOB blob;
2343                 enum ndr_err_code ndr_err;
2344                 struct spoolss_OSVersion os;
2345
2346                 os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
2347                                                       "spoolss", "os_major", 5);
2348                                                       /* Windows 2000 == 5.0 */
2349                 os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
2350                                                       "spoolss", "os_minor", 0);
2351                 os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
2352                                                       "spoolss", "os_build", 2195);
2353                 os.extra_string         = "";   /* leave extra string empty */
2354
2355                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2356                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2357                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2358                         return WERR_GENERAL_FAILURE;
2359                 }
2360
2361                 if (DEBUGLEVEL >= 10) {
2362                         NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2363                 }
2364
2365                 *type = REG_BINARY;
2366                 data->binary = blob;
2367
2368                 return WERR_OK;
2369         }
2370
2371
2372         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2373                 *type = REG_SZ;
2374
2375                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2376                 W_ERROR_HAVE_NO_MEMORY(data->string);
2377
2378                 return WERR_OK;
2379         }
2380
2381         if (!strcasecmp_m(value, "Architecture")) {
2382                 *type = REG_SZ;
2383                 data->string = talloc_strdup(mem_ctx,
2384                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2385                 W_ERROR_HAVE_NO_MEMORY(data->string);
2386
2387                 return WERR_OK;
2388         }
2389
2390         if (!strcasecmp_m(value, "DsPresent")) {
2391                 *type = REG_DWORD;
2392
2393                 /* only show the publish check box if we are a
2394                    member of a AD domain */
2395
2396                 if (lp_security() == SEC_ADS) {
2397                         SIVAL(&data->value, 0, 0x01);
2398                 } else {
2399                         SIVAL(&data->value, 0, 0x00);
2400                 }
2401                 return WERR_OK;
2402         }
2403
2404         if (!strcasecmp_m(value, "DNSMachineName")) {
2405                 const char *hostname = get_mydnsfullname();
2406
2407                 if (!hostname) {
2408                         return WERR_BADFILE;
2409                 }
2410
2411                 *type = REG_SZ;
2412                 data->string = talloc_strdup(mem_ctx, hostname);
2413                 W_ERROR_HAVE_NO_MEMORY(data->string);
2414
2415                 return WERR_OK;
2416         }
2417
2418         *type = REG_NONE;
2419
2420         return WERR_INVALID_PARAM;
2421 }
2422
2423 /****************************************************************
2424  _spoolss_GetPrinterData
2425 ****************************************************************/
2426
2427 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2428                                struct spoolss_GetPrinterData *r)
2429 {
2430         struct spoolss_GetPrinterDataEx r2;
2431
2432         r2.in.handle            = r->in.handle;
2433         r2.in.key_name          = "PrinterDriverData";
2434         r2.in.value_name        = r->in.value_name;
2435         r2.in.offered           = r->in.offered;
2436         r2.out.type             = r->out.type;
2437         r2.out.data             = r->out.data;
2438         r2.out.needed           = r->out.needed;
2439
2440         return _spoolss_GetPrinterDataEx(p, &r2);
2441 }
2442
2443 /*********************************************************
2444  Connect to the client machine.
2445 **********************************************************/
2446
2447 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2448                                       struct sockaddr_storage *client_ss, const char *remote_machine)
2449 {
2450         NTSTATUS ret;
2451         struct sockaddr_storage rm_addr;
2452         char addr[INET6_ADDRSTRLEN];
2453
2454         if ( is_zero_addr(client_ss) ) {
2455                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2456                         remote_machine));
2457                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2458                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2459                         return false;
2460                 }
2461                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2462         } else {
2463                 rm_addr = *client_ss;
2464                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2465                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2466                         addr));
2467         }
2468
2469         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2470                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2471                         addr));
2472                 return false;
2473         }
2474
2475         /* setup the connection */
2476         ret = cli_full_connection( pp_cli, lp_netbios_name(), remote_machine,
2477                 &rm_addr, 0, "IPC$", "IPC",
2478                 "", /* username */
2479                 "", /* domain */
2480                 "", /* password */
2481                 0, lp_client_signing());
2482
2483         if ( !NT_STATUS_IS_OK( ret ) ) {
2484                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2485                         remote_machine ));
2486                 return false;
2487         }
2488
2489         if ( smbXcli_conn_protocol((*pp_cli)->conn) != PROTOCOL_NT1 ) {
2490                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2491                 cli_shutdown(*pp_cli);
2492                 return false;
2493         }
2494
2495         /*
2496          * Ok - we have an anonymous connection to the IPC$ share.
2497          * Now start the NT Domain stuff :-).
2498          */
2499
2500         ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2501         if (!NT_STATUS_IS_OK(ret)) {
2502                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2503                         remote_machine, nt_errstr(ret)));
2504                 cli_shutdown(*pp_cli);
2505                 return false;
2506         }
2507
2508         return true;
2509 }
2510
2511 /***************************************************************************
2512  Connect to the client.
2513 ****************************************************************************/
2514
2515 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2516                                         uint32_t localprinter,
2517                                         enum winreg_Type type,
2518                                         struct policy_handle *handle,
2519                                         struct notify_back_channel **_chan,
2520                                         struct sockaddr_storage *client_ss,
2521                                         struct messaging_context *msg_ctx)
2522 {
2523         WERROR result;
2524         NTSTATUS status;
2525         struct notify_back_channel *chan;
2526
2527         for (chan = back_channels; chan; chan = chan->next) {
2528                 if (memcmp(&chan->client_address, client_ss,
2529                            sizeof(struct sockaddr_storage)) == 0) {
2530                         break;
2531                 }
2532         }
2533
2534         /*
2535          * If it's the first connection, contact the client
2536          * and connect to the IPC$ share anonymously
2537          */
2538         if (!chan) {
2539                 fstring unix_printer;
2540
2541                 /* the +2 is to strip the leading 2 backslashs */
2542                 fstrcpy(unix_printer, printer + 2);
2543
2544                 chan = talloc_zero(NULL, struct notify_back_channel);
2545                 if (!chan) {
2546                         return false;
2547                 }
2548                 chan->client_address = *client_ss;
2549
2550                 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2551                         TALLOC_FREE(chan);
2552                         return false;
2553                 }
2554
2555                 DLIST_ADD(back_channels, chan);
2556
2557                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2558                                    receive_notify2_message_list);
2559         }
2560
2561         if (chan->cli_pipe == NULL ||
2562             chan->cli_pipe->binding_handle == NULL) {
2563                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2564                         "NULL %s for printer %s\n",
2565                         chan->cli_pipe == NULL ?
2566                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2567                         printer));
2568                 return false;
2569         }
2570
2571         /*
2572          * Tell the specific printing tdb we want messages for this printer
2573          * by registering our PID.
2574          */
2575
2576         if (!print_notify_register_pid(snum)) {
2577                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2578                           printer));
2579         }
2580
2581         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2582                                                  talloc_tos(),
2583                                                  printer,
2584                                                  localprinter,
2585                                                  type,
2586                                                  0,
2587                                                  NULL,
2588                                                  handle,
2589                                                  &result);
2590         if (!NT_STATUS_IS_OK(status)) {
2591                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2592                 result = ntstatus_to_werror(status);
2593         } else if (!W_ERROR_IS_OK(result)) {
2594                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2595         }
2596
2597         chan->active_connections++;
2598         *_chan = chan;
2599
2600         return (W_ERROR_IS_OK(result));
2601 }
2602
2603 /****************************************************************
2604  ****************************************************************/
2605
2606 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2607                                                              const struct spoolss_NotifyOption *r)
2608 {
2609         struct spoolss_NotifyOption *option;
2610         uint32_t i,k;
2611
2612         if (!r) {
2613                 return NULL;
2614         }
2615
2616         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2617         if (!option) {
2618                 return NULL;
2619         }
2620
2621         *option = *r;
2622
2623         if (!option->count) {
2624                 return option;
2625         }
2626
2627         option->types = talloc_zero_array(option,
2628                 struct spoolss_NotifyOptionType, option->count);
2629         if (!option->types) {
2630                 talloc_free(option);
2631                 return NULL;
2632         }
2633
2634         for (i=0; i < option->count; i++) {
2635                 option->types[i] = r->types[i];
2636
2637                 if (option->types[i].count) {
2638                         option->types[i].fields = talloc_zero_array(option,
2639                                 union spoolss_Field, option->types[i].count);
2640                         if (!option->types[i].fields) {
2641                                 talloc_free(option);
2642                                 return NULL;
2643                         }
2644                         for (k=0; k<option->types[i].count; k++) {
2645                                 option->types[i].fields[k] =
2646                                         r->types[i].fields[k];
2647                         }
2648                 }
2649         }
2650
2651         return option;
2652 }
2653
2654 /****************************************************************
2655  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2656  *
2657  * before replying OK: status=0 a rpc call is made to the workstation
2658  * asking ReplyOpenPrinter
2659  *
2660  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2661  * called from api_spoolss_rffpcnex
2662 ****************************************************************/
2663
2664 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2665                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2666 {
2667         int snum = -1;
2668         struct spoolss_NotifyOption *option = r->in.notify_options;
2669         struct sockaddr_storage client_ss;
2670         ssize_t client_len;
2671
2672         /* store the notify value in the printer struct */
2673
2674         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2675
2676         if (!Printer) {
2677                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2678                         "Invalid handle (%s:%u:%u).\n",
2679                         OUR_HANDLE(r->in.handle)));
2680                 return WERR_BADFID;
2681         }
2682
2683         Printer->notify.flags           = r->in.flags;
2684         Printer->notify.options         = r->in.options;
2685         Printer->notify.printerlocal    = r->in.printer_local;
2686         Printer->notify.msg_ctx         = p->msg_ctx;
2687
2688         TALLOC_FREE(Printer->notify.option);
2689         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2690
2691         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2692
2693         /* Connect to the client machine and send a ReplyOpenPrinter */
2694
2695         if ( Printer->printer_type == SPLHND_SERVER)
2696                 snum = -1;
2697         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2698                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2699                 return WERR_BADFID;
2700
2701         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2702                   "remote_address is %s\n",
2703                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2704
2705         if (!lp_print_notify_backchannel(snum)) {
2706                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2707                         "backchannel disabled\n"));
2708                 return WERR_SERVER_UNAVAILABLE;
2709         }
2710
2711         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2712                                                   (struct sockaddr *) &client_ss,
2713                                                   sizeof(struct sockaddr_storage));
2714         if (client_len < 0) {
2715                 return WERR_NOMEM;
2716         }
2717
2718         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2719                                         Printer->notify.printerlocal, REG_SZ,
2720                                         &Printer->notify.cli_hnd,
2721                                         &Printer->notify.cli_chan,
2722                                         &client_ss, p->msg_ctx)) {
2723                 return WERR_SERVER_UNAVAILABLE;
2724         }
2725
2726         return WERR_OK;
2727 }
2728
2729 /*******************************************************************
2730  * fill a notify_info_data with the servername
2731  ********************************************************************/
2732
2733 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2734                                        int snum,
2735                                        struct spoolss_Notify *data,
2736                                        print_queue_struct *queue,
2737                                        struct spoolss_PrinterInfo2 *pinfo2,
2738                                        TALLOC_CTX *mem_ctx)
2739 {
2740         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2741 }
2742
2743 /*******************************************************************
2744  * fill a notify_info_data with the printername (not including the servername).
2745  ********************************************************************/
2746
2747 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2748                                         int snum,
2749                                         struct spoolss_Notify *data,
2750                                         print_queue_struct *queue,
2751                                         struct spoolss_PrinterInfo2 *pinfo2,
2752                                         TALLOC_CTX *mem_ctx)
2753 {
2754         /* the notify name should not contain the \\server\ part */
2755         const char *p = strrchr(pinfo2->printername, '\\');
2756
2757         if (!p) {
2758                 p = pinfo2->printername;
2759         } else {
2760                 p++;
2761         }
2762
2763         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2764 }
2765
2766 /*******************************************************************
2767  * fill a notify_info_data with the servicename
2768  ********************************************************************/
2769
2770 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2771                                       int snum,
2772                                       struct spoolss_Notify *data,
2773                                       print_queue_struct *queue,
2774                                       struct spoolss_PrinterInfo2 *pinfo2,
2775                                       TALLOC_CTX *mem_ctx)
2776 {
2777         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2778 }
2779
2780 /*******************************************************************
2781  * fill a notify_info_data with the port name
2782  ********************************************************************/
2783
2784 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2785                                      int snum,
2786                                      struct spoolss_Notify *data,
2787                                      print_queue_struct *queue,
2788                                      struct spoolss_PrinterInfo2 *pinfo2,
2789                                      TALLOC_CTX *mem_ctx)
2790 {
2791         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2792 }
2793
2794 /*******************************************************************
2795  * fill a notify_info_data with the printername
2796  * but it doesn't exist, have to see what to do
2797  ********************************************************************/
2798
2799 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2800                                        int snum,
2801                                        struct spoolss_Notify *data,
2802                                        print_queue_struct *queue,
2803                                        struct spoolss_PrinterInfo2 *pinfo2,
2804                                        TALLOC_CTX *mem_ctx)
2805 {
2806         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2807 }
2808
2809 /*******************************************************************
2810  * fill a notify_info_data with the comment
2811  ********************************************************************/
2812
2813 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2814                                    int snum,
2815                                    struct spoolss_Notify *data,
2816                                    print_queue_struct *queue,
2817                                    struct spoolss_PrinterInfo2 *pinfo2,
2818                                    TALLOC_CTX *mem_ctx)
2819 {
2820         const char *p;
2821
2822         if (*pinfo2->comment == '\0') {
2823                 p = lp_comment(talloc_tos(), snum);
2824         } else {
2825                 p = pinfo2->comment;
2826         }
2827
2828         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2829 }
2830
2831 /*******************************************************************
2832  * fill a notify_info_data with the comment
2833  * location = "Room 1, floor 2, building 3"
2834  ********************************************************************/
2835
2836 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2837                                     int snum,
2838                                     struct spoolss_Notify *data,
2839                                     print_queue_struct *queue,
2840                                     struct spoolss_PrinterInfo2 *pinfo2,
2841                                     TALLOC_CTX *mem_ctx)
2842 {
2843         const char *loc = pinfo2->location;
2844         NTSTATUS status;
2845
2846         status = printer_list_get_printer(mem_ctx,
2847                                           pinfo2->sharename,
2848                                           NULL,
2849                                           &loc,
2850                                           NULL);
2851         if (NT_STATUS_IS_OK(status)) {
2852                 if (loc == NULL) {
2853                         loc = pinfo2->location;
2854                 }
2855         }
2856
2857         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2858 }
2859
2860 /*******************************************************************
2861  * fill a notify_info_data with the device mode
2862  * jfm:xxxx don't to it for know but that's a real problem !!!
2863  ********************************************************************/
2864
2865 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2866                                    int snum,
2867                                    struct spoolss_Notify *data,
2868                                    print_queue_struct *queue,
2869                                    struct spoolss_PrinterInfo2 *pinfo2,
2870                                    TALLOC_CTX *mem_ctx)
2871 {
2872         /* for a dummy implementation we have to zero the fields */
2873         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2874 }
2875
2876 /*******************************************************************
2877  * fill a notify_info_data with the separator file name
2878  ********************************************************************/
2879
2880 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2881                                    int snum,
2882                                    struct spoolss_Notify *data,
2883                                    print_queue_struct *queue,
2884                                    struct spoolss_PrinterInfo2 *pinfo2,
2885                                    TALLOC_CTX *mem_ctx)
2886 {
2887         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2888 }
2889
2890 /*******************************************************************
2891  * fill a notify_info_data with the print processor
2892  * jfm:xxxx return always winprint to indicate we don't do anything to it
2893  ********************************************************************/
2894
2895 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2896                                            int snum,
2897                                            struct spoolss_Notify *data,
2898                                            print_queue_struct *queue,
2899                                            struct spoolss_PrinterInfo2 *pinfo2,
2900                                            TALLOC_CTX *mem_ctx)
2901 {
2902         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2903 }
2904
2905 /*******************************************************************
2906  * fill a notify_info_data with the print processor options
2907  * jfm:xxxx send an empty string
2908  ********************************************************************/
2909
2910 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2911                                       int snum,
2912                                       struct spoolss_Notify *data,
2913                                       print_queue_struct *queue,
2914                                       struct spoolss_PrinterInfo2 *pinfo2,
2915                                       TALLOC_CTX *mem_ctx)
2916 {
2917         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2918 }
2919
2920 /*******************************************************************
2921  * fill a notify_info_data with the data type
2922  * jfm:xxxx always send RAW as data type
2923  ********************************************************************/
2924
2925 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2926                                     int snum,
2927                                     struct spoolss_Notify *data,
2928                                     print_queue_struct *queue,
2929                                     struct spoolss_PrinterInfo2 *pinfo2,
2930                                     TALLOC_CTX *mem_ctx)
2931 {
2932         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2933 }
2934
2935 /*******************************************************************
2936  * fill a notify_info_data with the security descriptor
2937  * jfm:xxxx send an null pointer to say no security desc
2938  * have to implement security before !
2939  ********************************************************************/
2940
2941 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2942                                          int snum,
2943                                          struct spoolss_Notify *data,
2944                                          print_queue_struct *queue,
2945                                          struct spoolss_PrinterInfo2 *pinfo2,
2946                                          TALLOC_CTX *mem_ctx)
2947 {
2948         if (pinfo2->secdesc == NULL) {
2949                 data->data.sd.sd = NULL;
2950         } else {
2951                 data->data.sd.sd = security_descriptor_copy(mem_ctx,
2952                                                             pinfo2->secdesc);
2953         }
2954         data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2955                                                              0);
2956 }
2957
2958 /*******************************************************************
2959  * fill a notify_info_data with the attributes
2960  * jfm:xxxx a samba printer is always shared
2961  ********************************************************************/
2962
2963 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2964                                       int snum,
2965                                       struct spoolss_Notify *data,
2966                                       print_queue_struct *queue,
2967                                       struct spoolss_PrinterInfo2 *pinfo2,
2968                                       TALLOC_CTX *mem_ctx)
2969 {
2970         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2971 }
2972
2973 /*******************************************************************
2974  * fill a notify_info_data with the priority
2975  ********************************************************************/
2976
2977 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2978                                     int snum,
2979                                     struct spoolss_Notify *data,
2980                                     print_queue_struct *queue,
2981                                     struct spoolss_PrinterInfo2 *pinfo2,
2982                                     TALLOC_CTX *mem_ctx)
2983 {
2984         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2985 }
2986
2987 /*******************************************************************
2988  * fill a notify_info_data with the default priority
2989  ********************************************************************/
2990
2991 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2992                                             int snum,
2993                                             struct spoolss_Notify *data,
2994                                             print_queue_struct *queue,
2995                                             struct spoolss_PrinterInfo2 *pinfo2,
2996                                             TALLOC_CTX *mem_ctx)
2997 {
2998         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2999 }
3000
3001 /*******************************************************************
3002  * fill a notify_info_data with the start time
3003  ********************************************************************/
3004
3005 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3006                                       int snum,
3007                                       struct spoolss_Notify *data,
3008                                       print_queue_struct *queue,
3009                                       struct spoolss_PrinterInfo2 *pinfo2,
3010                                       TALLOC_CTX *mem_ctx)
3011 {
3012         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3013 }
3014
3015 /*******************************************************************
3016  * fill a notify_info_data with the until time
3017  ********************************************************************/
3018
3019 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3020                                       int snum,
3021                                       struct spoolss_Notify *data,
3022                                       print_queue_struct *queue,
3023                                       struct spoolss_PrinterInfo2 *pinfo2,
3024                                       TALLOC_CTX *mem_ctx)
3025 {
3026         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3027 }
3028
3029 /*******************************************************************
3030  * fill a notify_info_data with the status
3031  ********************************************************************/
3032
3033 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3034                                   int snum,
3035                                   struct spoolss_Notify *data,
3036                                   print_queue_struct *queue,
3037                                   struct spoolss_PrinterInfo2 *pinfo2,
3038                                   TALLOC_CTX *mem_ctx)
3039 {
3040         print_status_struct status;
3041
3042         print_queue_length(msg_ctx, snum, &status);
3043         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3044 }
3045
3046 /*******************************************************************
3047  * fill a notify_info_data with the number of jobs queued
3048  ********************************************************************/
3049
3050 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3051                                  int snum,
3052                                  struct spoolss_Notify *data,
3053                                  print_queue_struct *queue,
3054                                  struct spoolss_PrinterInfo2 *pinfo2,
3055                                  TALLOC_CTX *mem_ctx)
3056 {
3057         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3058                 data, print_queue_length(msg_ctx, snum, NULL));
3059 }
3060
3061 /*******************************************************************
3062  * fill a notify_info_data with the average ppm
3063  ********************************************************************/
3064
3065 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3066                                        int snum,
3067                                        struct spoolss_Notify *data,
3068                                        print_queue_struct *queue,
3069                                        struct spoolss_PrinterInfo2 *pinfo2,
3070                                        TALLOC_CTX *mem_ctx)
3071 {
3072         /* always respond 8 pages per minutes */
3073         /* a little hard ! */
3074         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3075 }
3076
3077 /*******************************************************************
3078  * fill a notify_info_data with username
3079  ********************************************************************/
3080
3081 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3082                                     int snum,
3083                                     struct spoolss_Notify *data,
3084                                     print_queue_struct *queue,
3085                                     struct spoolss_PrinterInfo2 *pinfo2,
3086                                     TALLOC_CTX *mem_ctx)
3087 {
3088         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3089 }
3090
3091 /*******************************************************************
3092  * fill a notify_info_data with job status
3093  ********************************************************************/
3094
3095 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3096                                       int snum,
3097                                       struct spoolss_Notify *data,
3098                                       print_queue_struct *queue,
3099                                       struct spoolss_PrinterInfo2 *pinfo2,
3100                                       TALLOC_CTX *mem_ctx)
3101 {
3102         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3103 }
3104
3105 /*******************************************************************
3106  * fill a notify_info_data with job name
3107  ********************************************************************/
3108
3109 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3110                                     int snum,
3111                                     struct spoolss_Notify *data,
3112                                     print_queue_struct *queue,
3113                                     struct spoolss_PrinterInfo2 *pinfo2,
3114                                     TALLOC_CTX *mem_ctx)
3115 {
3116         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3117 }
3118
3119 /*******************************************************************
3120  * fill a notify_info_data with job status
3121  ********************************************************************/
3122
3123 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3124                                              int snum,
3125                                              struct spoolss_Notify *data,
3126                                              print_queue_struct *queue,
3127                                              struct spoolss_PrinterInfo2 *pinfo2,
3128                                              TALLOC_CTX *mem_ctx)
3129 {
3130         /*
3131          * Now we're returning job status codes we just return a "" here. JRA.
3132          */
3133
3134         const char *p = "";
3135
3136 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3137         p = "unknown";
3138
3139         switch (queue->status) {
3140         case LPQ_QUEUED:
3141                 p = "Queued";
3142                 break;
3143         case LPQ_PAUSED:
3144                 p = "";    /* NT provides the paused string */
3145                 break;
3146         case LPQ_SPOOLING:
3147                 p = "Spooling";
3148                 break;
3149         case LPQ_PRINTING:
3150                 p = "Printing";
3151                 break;
3152         }
3153 #endif /* NO LONGER NEEDED. */
3154
3155         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3156 }
3157
3158 /*******************************************************************
3159  * fill a notify_info_data with job time
3160  ********************************************************************/
3161
3162 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3163                                     int snum,
3164                                     struct spoolss_Notify *data,
3165                                     print_queue_struct *queue,
3166                                     struct spoolss_PrinterInfo2 *pinfo2,
3167                                     TALLOC_CTX *mem_ctx)
3168 {
3169         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3170 }
3171
3172 /*******************************************************************
3173  * fill a notify_info_data with job size
3174  ********************************************************************/
3175
3176 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3177                                     int snum,
3178                                     struct spoolss_Notify *data,
3179                                     print_queue_struct *queue,
3180                                     struct spoolss_PrinterInfo2 *pinfo2,
3181                                     TALLOC_CTX *mem_ctx)
3182 {
3183         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3184 }
3185
3186 /*******************************************************************
3187  * fill a notify_info_data with page info
3188  ********************************************************************/
3189 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3190                                        int snum,
3191                                 struct spoolss_Notify *data,
3192                                 print_queue_struct *queue,
3193                                 struct spoolss_PrinterInfo2 *pinfo2,
3194                                 TALLOC_CTX *mem_ctx)
3195 {
3196         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3197 }
3198
3199 /*******************************************************************
3200  * fill a notify_info_data with pages printed info.
3201  ********************************************************************/
3202 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3203                                          int snum,
3204                                 struct spoolss_Notify *data,
3205                                 print_queue_struct *queue,
3206                                 struct spoolss_PrinterInfo2 *pinfo2,
3207                                 TALLOC_CTX *mem_ctx)
3208 {
3209         /* Add code when back-end tracks this */
3210         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3211 }
3212
3213 /*******************************************************************
3214  Fill a notify_info_data with job position.
3215  ********************************************************************/
3216
3217 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3218                                         int snum,
3219                                         struct spoolss_Notify *data,
3220                                         print_queue_struct *queue,
3221                                         struct spoolss_PrinterInfo2 *pinfo2,
3222                                         TALLOC_CTX *mem_ctx)
3223 {
3224         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3225 }
3226
3227 /*******************************************************************
3228  Fill a notify_info_data with submitted time.
3229  ********************************************************************/
3230
3231 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3232                                           int snum,
3233                                           struct spoolss_Notify *data,
3234                                           print_queue_struct *queue,
3235                                           struct spoolss_PrinterInfo2 *pinfo2,
3236                                           TALLOC_CTX *mem_ctx)
3237 {
3238         data->data.string.string = NULL;
3239         data->data.string.size = 0;
3240
3241         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3242                                &data->data.string.string,
3243                                &data->data.string.size);
3244
3245 }
3246
3247 struct s_notify_info_data_table
3248 {
3249         enum spoolss_NotifyType type;
3250         uint16_t field;
3251         const char *name;
3252         enum spoolss_NotifyTable variable_type;
3253         void (*fn) (struct messaging_context *msg_ctx,
3254                     int snum, struct spoolss_Notify *data,
3255                     print_queue_struct *queue,
3256                     struct spoolss_PrinterInfo2 *pinfo2,
3257                     TALLOC_CTX *mem_ctx);
3258 };
3259
3260 /* A table describing the various print notification constants and
3261    whether the notification data is a pointer to a variable sized
3262    buffer, a one value uint32_t or a two value uint32_t. */
3263
3264 static const struct s_notify_info_data_table notify_info_data_table[] =
3265 {
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3292 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3293 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3294 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3295 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3296 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3301 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3302 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3304 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3305 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3306 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3307 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3308 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3309 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3311 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3313 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3314 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3315 };
3316
3317 /*******************************************************************
3318  Return the variable_type of info_data structure.
3319 ********************************************************************/
3320
3321 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3322                                                                   uint16_t field)
3323 {
3324         int i=0;
3325
3326         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3327                 if ( (notify_info_data_table[i].type == type) &&
3328                      (notify_info_data_table[i].field == field) ) {
3329                         return notify_info_data_table[i].variable_type;
3330                 }
3331         }
3332
3333         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3334
3335         return (enum spoolss_NotifyTable) 0;
3336 }
3337
3338 /****************************************************************************
3339 ****************************************************************************/
3340
3341 static bool search_notify(enum spoolss_NotifyType type,
3342                           uint16_t field,
3343                           int *value)
3344 {
3345         int i;
3346
3347         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3348                 if (notify_info_data_table[i].type == type &&
3349                     notify_info_data_table[i].field == field &&
3350                     notify_info_data_table[i].fn != NULL) {
3351                         *value = i;
3352                         return true;
3353                 }
3354         }
3355
3356         return false;
3357 }
3358
3359 /****************************************************************************
3360 ****************************************************************************/
3361
3362 static void construct_info_data(struct spoolss_Notify *info_data,
3363                                 enum spoolss_NotifyType type,
3364                                 uint16_t field, int id)
3365 {
3366         info_data->type                 = type;
3367         info_data->field.field          = field;
3368         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3369         info_data->job_id               = id;
3370 }
3371
3372 /*******************************************************************
3373  *
3374  * fill a notify_info struct with info asked
3375  *
3376  ********************************************************************/
3377
3378 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3379                                           struct printer_handle *print_hnd,
3380                                           struct spoolss_NotifyInfo *info,
3381                                           struct spoolss_PrinterInfo2 *pinfo2,
3382                                           int snum,
3383                                           const struct spoolss_NotifyOptionType *option_type,
3384                                           uint32_t id,
3385                                           TALLOC_CTX *mem_ctx)
3386 {
3387         int field_num,j;
3388         enum spoolss_NotifyType type;
3389         uint16_t field;
3390
3391         struct spoolss_Notify *current_data;
3392
3393         type = option_type->type;
3394
3395         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3396                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3397                 option_type->count, lp_servicename(talloc_tos(), snum)));
3398
3399         for(field_num=0; field_num < option_type->count; field_num++) {
3400                 field = option_type->fields[field_num].field;
3401
3402                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3403
3404                 if (!search_notify(type, field, &j) )
3405                         continue;
3406
3407                 info->notifies = talloc_realloc(info, info->notifies,
3408                                                       struct spoolss_Notify,
3409                                                       info->count + 1);
3410                 if (info->notifies == NULL) {
3411                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3412                         return false;
3413                 }
3414
3415                 current_data = &info->notifies[info->count];
3416
3417                 construct_info_data(current_data, type, field, id);
3418
3419                 DEBUG(10, ("construct_notify_printer_info: "
3420                            "calling [%s]  snum=%d  printername=[%s])\n",
3421                            notify_info_data_table[j].name, snum,
3422                            pinfo2->printername));
3423
3424                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3425                                              NULL, pinfo2, mem_ctx);
3426
3427                 info->count++;
3428         }
3429
3430         return true;
3431 }
3432
3433 /*******************************************************************
3434  *
3435  * fill a notify_info struct with info asked
3436  *
3437  ********************************************************************/
3438
3439 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3440                                        print_queue_struct *queue,
3441                                        struct spoolss_NotifyInfo *info,
3442                                        struct spoolss_PrinterInfo2 *pinfo2,
3443                                        int snum,
3444                                        const struct spoolss_NotifyOptionType *option_type,
3445                                        uint32_t id,
3446                                        TALLOC_CTX *mem_ctx)
3447 {
3448         int field_num,j;
3449         enum spoolss_NotifyType type;
3450         uint16_t field;
3451         struct spoolss_Notify *current_data;
3452
3453         DEBUG(4,("construct_notify_jobs_info\n"));
3454
3455         type = option_type->type;
3456
3457         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3458                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3459                 option_type->count));
3460
3461         for(field_num=0; field_num<option_type->count; field_num++) {
3462                 field = option_type->fields[field_num].field;
3463
3464                 if (!search_notify(type, field, &j) )
3465                         continue;
3466
3467                 info->notifies = talloc_realloc(info, info->notifies,
3468                                                       struct spoolss_Notify,
3469                                                       info->count + 1);
3470                 if (info->notifies == NULL) {
3471                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3472                         return false;
3473                 }
3474
3475                 current_data=&(info->notifies[info->count]);
3476
3477                 construct_info_data(current_data, type, field, id);
3478                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3479                                              queue, pinfo2, mem_ctx);
3480                 info->count++;
3481         }
3482
3483         return true;
3484 }
3485
3486 /*
3487  * JFM: The enumeration is not that simple, it's even non obvious.
3488  *
3489  * let's take an example: I want to monitor the PRINTER SERVER for
3490  * the printer's name and the number of jobs currently queued.
3491  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3492  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3493  *
3494  * I have 3 printers on the back of my server.
3495  *
3496  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3497  * structures.
3498  *   Number     Data                    Id
3499  *      1       printer 1 name          1
3500  *      2       printer 1 cjob          1
3501  *      3       printer 2 name          2
3502  *      4       printer 2 cjob          2
3503  *      5       printer 3 name          3
3504  *      6       printer 3 name          3
3505  *
3506  * that's the print server case, the printer case is even worse.
3507  */
3508
3509 /*******************************************************************
3510  *
3511  * enumerate all printers on the printserver
3512  * fill a notify_info struct with info asked
3513  *
3514  ********************************************************************/
3515
3516 static WERROR printserver_notify_info(struct pipes_struct *p,
3517                                       struct policy_handle *hnd,
3518                                       struct spoolss_NotifyInfo *info,
3519                                       TALLOC_CTX *mem_ctx)
3520 {
3521         int snum;
3522         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3523         int n_services=lp_numservices();
3524         int i;
3525         struct spoolss_NotifyOption *option;
3526         struct spoolss_NotifyOptionType option_type;
3527         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3528         WERROR result;
3529
3530         DEBUG(4,("printserver_notify_info\n"));
3531
3532         if (!Printer)
3533                 return WERR_BADFID;
3534
3535         option = Printer->notify.option;
3536
3537         info->version   = 2;
3538         info->notifies  = NULL;
3539         info->count     = 0;
3540
3541         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3542            sending a ffpcn() request first */
3543
3544         if ( !option )
3545                 return WERR_BADFID;
3546
3547         for (i=0; i<option->count; i++) {
3548                 option_type = option->types[i];
3549
3550                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3551                         continue;
3552
3553                 for (snum = 0; snum < n_services; snum++) {
3554                         if (!lp_browseable(snum) ||
3555                             !lp_snum_ok(snum) ||
3556                             !lp_printable(snum)) {
3557                                 continue; /* skip */
3558                         }
3559
3560                         /* Maybe we should use the SYSTEM session_info here... */
3561                         result = winreg_get_printer_internal(mem_ctx,
3562                                                     get_session_info_system(),
3563                                                     p->msg_ctx,
3564                                                     lp_servicename(talloc_tos(), snum),
3565                                                     &pinfo2);
3566                         if (!W_ERROR_IS_OK(result)) {
3567                                 DEBUG(4, ("printserver_notify_info: "
3568                                           "Failed to get printer [%s]\n",
3569                                           lp_servicename(talloc_tos(), snum)));
3570                                 continue;
3571                         }
3572
3573
3574                         construct_notify_printer_info(p->msg_ctx,
3575                                                       Printer, info,
3576                                                       pinfo2, snum,
3577                                                       &option_type, snum,
3578                                                       mem_ctx);
3579
3580                         TALLOC_FREE(pinfo2);
3581                 }
3582         }
3583
3584 #if 0
3585         /*
3586          * Debugging information, don't delete.
3587          */
3588
3589         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3590         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3591         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3592
3593         for (i=0; i<info->count; i++) {
3594                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3595                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3596                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3597         }
3598 #endif
3599
3600         return WERR_OK;
3601 }
3602
3603 /*******************************************************************
3604  *
3605  * fill a notify_info struct with info asked
3606  *
3607  ********************************************************************/
3608
3609 static WERROR printer_notify_info(struct pipes_struct *p,
3610                                   struct policy_handle *hnd,
3611                                   struct spoolss_NotifyInfo *info,
3612                                   TALLOC_CTX *mem_ctx)
3613 {
3614         int snum;
3615         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3616         int i;
3617         uint32_t id;
3618         struct spoolss_NotifyOption *option;
3619         struct spoolss_NotifyOptionType option_type;
3620         int count,j;
3621         print_queue_struct *queue=NULL;
3622         print_status_struct status;
3623         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3624         WERROR result;
3625         struct tdb_print_db *pdb;
3626
3627         DEBUG(4,("printer_notify_info\n"));
3628
3629         if (!Printer)
3630                 return WERR_BADFID;
3631
3632         option = Printer->notify.option;
3633         id = 0x0;
3634
3635         info->version   = 2;
3636         info->notifies  = NULL;
3637         info->count     = 0;
3638
3639         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3640            sending a ffpcn() request first */
3641
3642         if ( !option )
3643                 return WERR_BADFID;
3644
3645         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3646                 return WERR_BADFID;
3647         }
3648
3649         pdb = get_print_db_byname(Printer->sharename);
3650         if (pdb == NULL) {
3651                 return WERR_BADFID;
3652         }
3653
3654         /* Maybe we should use the SYSTEM session_info here... */
3655         result = winreg_get_printer_internal(mem_ctx,
3656                                     get_session_info_system(),
3657                                     p->msg_ctx,
3658                                     lp_servicename(talloc_tos(), snum), &pinfo2);
3659         if (!W_ERROR_IS_OK(result)) {
3660                 result = WERR_BADFID;
3661                 goto err_pdb_drop;
3662         }
3663
3664         /*
3665          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3666          * correct servername.
3667          */
3668         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3669         if (pinfo2->servername == NULL) {
3670                 result = WERR_NOMEM;
3671                 goto err_pdb_drop;
3672         }
3673
3674         for (i = 0; i < option->count; i++) {
3675                 option_type = option->types[i];
3676
3677                 switch (option_type.type) {
3678                 case PRINTER_NOTIFY_TYPE:
3679                         if (construct_notify_printer_info(p->msg_ctx,
3680                                                           Printer, info,
3681                                                           pinfo2, snum,
3682                                                           &option_type, id,
3683                                                           mem_ctx)) {
3684                                 id--;
3685                         }
3686                         break;
3687
3688                 case JOB_NOTIFY_TYPE:
3689
3690                         count = print_queue_status(p->msg_ctx, snum, &queue,
3691                                                    &status);
3692
3693                         for (j = 0; j < count; j++) {
3694                                 uint32_t jobid;
3695                                 jobid = sysjob_to_jobid_pdb(pdb,
3696                                                             queue[j].sysjob);
3697                                 if (jobid == (uint32_t)-1) {
3698                                         DEBUG(2, ("ignoring untracked job %d\n",
3699                                                   queue[j].sysjob));
3700                                         continue;
3701                                 }
3702                                 /* FIXME check return value */
3703                                 construct_notify_jobs_info(p->msg_ctx,
3704                                                            &queue[j], info,
3705                                                            pinfo2, snum,
3706                                                            &option_type,
3707                                                            jobid,
3708                                                            mem_ctx);
3709                         }
3710
3711                         SAFE_FREE(queue);
3712                         break;
3713                 }
3714         }
3715
3716         /*
3717          * Debugging information, don't delete.
3718          */
3719         /*
3720         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3721         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3722         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3723
3724         for (i=0; i<info->count; i++) {
3725                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3726                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3727                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3728         }
3729         */
3730
3731         talloc_free(pinfo2);
3732         result = WERR_OK;
3733 err_pdb_drop:
3734         release_print_db(pdb);
3735         return result;
3736 }
3737
3738 /****************************************************************
3739  _spoolss_RouterRefreshPrinterChangeNotify
3740 ****************************************************************/
3741
3742 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3743                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3744 {
3745         struct spoolss_NotifyInfo *info;
3746
3747         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3748         WERROR result = WERR_BADFID;
3749
3750         /* we always have a spoolss_NotifyInfo struct */
3751         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3752         if (!info) {
3753                 result = WERR_NOMEM;
3754                 goto done;
3755         }
3756
3757         *r->out.info = info;
3758
3759         if (!Printer) {
3760                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3761                         "Invalid handle (%s:%u:%u).\n",
3762                         OUR_HANDLE(r->in.handle)));
3763                 goto done;
3764         }
3765
3766         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3767
3768         /*
3769          *      We are now using the change value, and
3770          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3771          *      I don't have a global notification system, I'm sending back all the
3772          *      information even when _NOTHING_ has changed.
3773          */
3774
3775         /* We need to keep track of the change value to send back in
3776            RRPCN replies otherwise our updates are ignored. */
3777
3778         Printer->notify.fnpcn = true;
3779
3780         if (Printer->notify.cli_chan != NULL &&
3781             Printer->notify.cli_chan->active_connections > 0) {
3782                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3783                         "Saving change value in request [%x]\n",
3784                         r->in.change_low));
3785                 Printer->notify.change = r->in.change_low;
3786         }
3787
3788         /* just ignore the spoolss_NotifyOption */
3789
3790         switch (Printer->printer_type) {
3791                 case SPLHND_SERVER:
3792                         result = printserver_notify_info(p, r->in.handle,
3793                                                          info, p->mem_ctx);
3794                         break;
3795
3796                 case SPLHND_PRINTER:
3797                         result = printer_notify_info(p, r->in.handle,
3798                                                      info, p->mem_ctx);
3799                         break;
3800         }
3801
3802         Printer->notify.fnpcn = false;
3803
3804 done:
3805         return result;
3806 }
3807
3808 /********************************************************************
3809  ********************************************************************/
3810
3811 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3812                                  const char *servername,
3813                                  const char *printername,
3814                                  const char **printername_p)
3815 {
3816         /* FIXME: add lp_force_printername() */
3817
3818         if (servername == NULL) {
3819                 *printername_p = talloc_strdup(mem_ctx, printername);
3820                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3821                 return WERR_OK;
3822         }
3823
3824         if (servername[0] == '\\' && servername[1] == '\\') {
3825                 servername += 2;
3826         }
3827
3828         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3829         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3830
3831         return WERR_OK;
3832 }
3833
3834 /********************************************************************
3835  ********************************************************************/
3836
3837 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3838                                           const char *printername)
3839 {
3840         if (dm == NULL) {
3841                 return;
3842         }
3843
3844         dm->devicename = talloc_strndup(dm, printername,
3845                                         MIN(strlen(printername), 31));
3846 }
3847
3848 /********************************************************************
3849  * construct_printer_info_0
3850  * fill a printer_info_0 struct
3851  ********************************************************************/
3852
3853 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3854                                       const struct auth_session_info *session_info,
3855                                       struct messaging_context *msg_ctx,
3856                                       struct spoolss_PrinterInfo2 *info2,
3857                                       const char *servername,
3858                                       struct spoolss_PrinterInfo0 *r,
3859                                       int snum)
3860 {
3861         int count;
3862         struct printer_session_counter *session_counter;
3863         struct timeval setuptime;
3864         print_status_struct status;
3865         WERROR result;
3866
3867         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3868         if (!W_ERROR_IS_OK(result)) {
3869                 return result;
3870         }
3871
3872         if (servername) {
3873                 r->servername = talloc_strdup(mem_ctx, servername);
3874                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3875         } else {
3876                 r->servername = NULL;
3877         }
3878
3879         count = print_queue_length(msg_ctx, snum, &status);
3880
3881         /* check if we already have a counter for this printer */
3882         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3883                 if (session_counter->snum == snum)
3884                         break;
3885         }
3886
3887         /* it's the first time, add it to the list */
3888         if (session_counter == NULL) {
3889                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3890                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3891                 session_counter->snum           = snum;
3892                 session_counter->counter        = 0;
3893                 DLIST_ADD(counter_list, session_counter);
3894         }
3895
3896         /* increment it */
3897         session_counter->counter++;
3898
3899         r->cjobs                        = count;
3900         r->total_jobs                   = 0;
3901         r->total_bytes                  = 0;
3902
3903         get_startup_time(&setuptime);
3904         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3905
3906         /* JFM:
3907          * the global_counter should be stored in a TDB as it's common to all the clients
3908          * and should be zeroed on samba startup
3909          */
3910         r->global_counter               = session_counter->counter;
3911         r->total_pages                  = 0;
3912         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3913         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3914         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3915         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3916         r->spooling                     = 0;
3917         r->max_spooling                 = 0;
3918         r->session_counter              = session_counter->counter;
3919         r->num_error_out_of_paper       = 0x0;
3920         r->num_error_not_ready          = 0x0;          /* number of print failure */
3921         r->job_error                    = 0x0;
3922         r->number_of_processors         = 0x1;
3923         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3924         r->high_part_total_bytes        = 0x0;
3925
3926         /* ChangeID in milliseconds*/
3927         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3928                                     info2->sharename, &r->change_id);
3929
3930         r->last_error                   = WERR_OK;
3931         r->status                       = nt_printq_status(status.status);
3932         r->enumerate_network_printers   = 0x0;
3933         r->c_setprinter                 = 0x0;
3934         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3935         r->processor_level              = 0x6;          /* 6  ???*/
3936         r->ref_ic                       = 0;
3937         r->reserved2                    = 0;
3938         r->reserved3                    = 0;
3939
3940         return WERR_OK;
3941 }
3942
3943
3944 /********************************************************************
3945  * construct_printer_info1
3946  * fill a spoolss_PrinterInfo1 struct
3947 ********************************************************************/
3948
3949 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3950                                       const struct spoolss_PrinterInfo2 *info2,
3951                                       uint32_t flags,
3952                                       const char *servername,
3953                                       struct spoolss_PrinterInfo1 *r,
3954                                       int snum)
3955 {
3956         WERROR result;
3957
3958         r->flags                = flags;
3959
3960         if (info2->comment == NULL || info2->comment[0] == '\0') {
3961                 r->comment      = lp_comment(mem_ctx, snum);
3962         } else {
3963                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3964         }
3965         W_ERROR_HAVE_NO_MEMORY(r->comment);
3966
3967         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3968         if (!W_ERROR_IS_OK(result)) {
3969                 return result;
3970         }
3971
3972         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3973                                                   r->name,
3974                                                   info2->drivername,
3975                                                   r->comment);
3976         W_ERROR_HAVE_NO_MEMORY(r->description);
3977
3978         return WERR_OK;
3979 }
3980
3981 /********************************************************************
3982  * construct_printer_info2
3983  * fill a spoolss_PrinterInfo2 struct
3984 ********************************************************************/
3985
3986 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3987                                       struct messaging_context *msg_ctx,
3988                                       const struct spoolss_PrinterInfo2 *info2,
3989                                       const char *servername,
3990                                       struct spoolss_PrinterInfo2 *r,
3991                                       int snum)
3992 {
3993         int count;
3994         print_status_struct status;
3995         WERROR result;
3996
3997         count = print_queue_length(msg_ctx, snum, &status);
3998
3999         if (servername) {
4000                 r->servername           = talloc_strdup(mem_ctx, servername);
4001                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4002         } else {
4003                 r->servername           = NULL;
4004         }
4005
4006         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4007         if (!W_ERROR_IS_OK(result)) {
4008                 return result;
4009         }
4010
4011         r->sharename            = lp_servicename(mem_ctx, snum);
4012         W_ERROR_HAVE_NO_MEMORY(r->sharename);
4013         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4014         W_ERROR_HAVE_NO_MEMORY(r->portname);
4015         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4016         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4017
4018         if (info2->comment[0] == '\0') {
4019                 r->comment      = lp_comment(mem_ctx, snum);
4020         } else {
4021                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4022         }
4023         W_ERROR_HAVE_NO_MEMORY(r->comment);
4024
4025         r->location     = talloc_strdup(mem_ctx, info2->location);
4026         if (info2->location[0] == '\0') {
4027                 const char *loc = NULL;
4028                 NTSTATUS nt_status;
4029
4030                 nt_status = printer_list_get_printer(mem_ctx,
4031                                                      info2->sharename,
4032                                                      NULL,
4033                                                      &loc,
4034                                                      NULL);
4035                 if (NT_STATUS_IS_OK(nt_status)) {
4036                         if (loc != NULL) {
4037                                 r->location = talloc_strdup(mem_ctx, loc);
4038                         }
4039                 }
4040         }
4041         W_ERROR_HAVE_NO_MEMORY(r->location);
4042
4043         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4044         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4045         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4046         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4047         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4048         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4049         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4050         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4051
4052         r->attributes           = info2->attributes;
4053
4054         r->priority             = info2->priority;
4055         r->defaultpriority      = info2->defaultpriority;
4056         r->starttime            = info2->starttime;
4057         r->untiltime            = info2->untiltime;
4058         r->status               = nt_printq_status(status.status);
4059         r->cjobs                = count;
4060         r->averageppm           = info2->averageppm;
4061
4062         if (info2->devmode != NULL) {
4063                 result = copy_devicemode(mem_ctx,
4064                                          info2->devmode,
4065                                          &r->devmode);
4066                 if (!W_ERROR_IS_OK(result)) {
4067                         return result;
4068                 }
4069         } else if (lp_default_devmode(snum)) {
4070                 result = spoolss_create_default_devmode(mem_ctx,
4071                                                         info2->printername,
4072                                                         &r->devmode);
4073                 if (!W_ERROR_IS_OK(result)) {
4074                         return result;
4075                 }
4076         } else {
4077                 r->devmode = NULL;
4078                 DEBUG(8,("Returning NULL Devicemode!\n"));
4079         }
4080
4081         compose_devicemode_devicename(r->devmode, r->printername);
4082
4083         r->secdesc = NULL;
4084
4085         if (info2->secdesc != NULL) {
4086                 /* don't use talloc_steal() here unless you do a deep steal of all
4087                    the SEC_DESC members */
4088
4089                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4090                 if (r->secdesc == NULL) {
4091                         return WERR_NOMEM;
4092                 }
4093         }
4094
4095         return WERR_OK;
4096 }
4097
4098 /********************************************************************
4099  * construct_printer_info3
4100  * fill a spoolss_PrinterInfo3 struct
4101  ********************************************************************/
4102
4103 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4104                                       const struct spoolss_PrinterInfo2 *info2,
4105                                       const char *servername,
4106                                       struct spoolss_PrinterInfo3 *r,
4107                                       int snum)
4108 {
4109         /* These are the components of the SD we are returning. */
4110
4111         if (info2->secdesc != NULL) {
4112                 /* don't use talloc_steal() here unless you do a deep steal of all
4113                    the SEC_DESC members */
4114
4115                 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4116                 if (r->secdesc == NULL) {
4117                         return WERR_NOMEM;
4118                 }
4119         }
4120
4121         return WERR_OK;
4122 }
4123
4124 /********************************************************************
4125  * construct_printer_info4
4126  * fill a spoolss_PrinterInfo4 struct
4127  ********************************************************************/
4128
4129 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4130                                       const struct spoolss_PrinterInfo2 *info2,
4131                                       const char *servername,
4132                                       struct spoolss_PrinterInfo4 *r,
4133                                       int snum)
4134 {
4135         WERROR result;
4136
4137         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4138         if (!W_ERROR_IS_OK(result)) {
4139                 return result;
4140         }
4141
4142         if (servername) {
4143                 r->servername   = talloc_strdup(mem_ctx, servername);
4144                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4145         } else {
4146                 r->servername = NULL;
4147         }
4148
4149         r->attributes   = info2->attributes;
4150
4151         return WERR_OK;
4152 }
4153
4154 /********************************************************************
4155  * construct_printer_info5
4156  * fill a spoolss_PrinterInfo5 struct
4157  ********************************************************************/
4158
4159 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4160                                       const struct spoolss_PrinterInfo2 *info2,
4161                                       const char *servername,
4162                                       struct spoolss_PrinterInfo5 *r,
4163                                       int snum)
4164 {
4165         WERROR result;
4166
4167         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4168         if (!W_ERROR_IS_OK(result)) {
4169                 return result;
4170         }
4171
4172         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4173         W_ERROR_HAVE_NO_MEMORY(r->portname);
4174
4175         r->attributes   = info2->attributes;
4176
4177         /* these two are not used by NT+ according to MSDN */
4178         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4179         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4180
4181         return WERR_OK;
4182 }
4183
4184 /********************************************************************
4185  * construct_printer_info_6
4186  * fill a spoolss_PrinterInfo6 struct
4187  ********************************************************************/
4188
4189 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4190                                       struct messaging_context *msg_ctx,
4191                                       const struct spoolss_PrinterInfo2 *info2,
4192                                       const char *servername,
4193                                       struct spoolss_PrinterInfo6 *r,
4194                                       int snum)
4195 {
4196         print_status_struct status;
4197
4198         print_queue_length(msg_ctx, snum, &status);
4199
4200         r->status = nt_printq_status(status.status);
4201
4202         return WERR_OK;
4203 }
4204
4205 /********************************************************************
4206  * construct_printer_info7
4207  * fill a spoolss_PrinterInfo7 struct
4208  ********************************************************************/
4209
4210 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4211                                       struct messaging_context *msg_ctx,
4212                                       const char *servername,
4213                                       struct spoolss_PrinterInfo7 *r,
4214                                       int snum)
4215 {
4216         const struct auth_session_info *session_info;
4217         char *printer;
4218         WERROR werr;
4219         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4220         if (tmp_ctx == NULL) {
4221                 return WERR_NOMEM;
4222         }
4223
4224         session_info = get_session_info_system();
4225         SMB_ASSERT(session_info != NULL);
4226
4227         printer = lp_servicename(tmp_ctx, snum);
4228         if (printer == NULL) {
4229                 DEBUG(0, ("invalid printer snum %d\n", snum));
4230                 werr = WERR_INVALID_PARAM;
4231                 goto out_tmp_free;
4232         }
4233
4234         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4235                                  servername, printer, NULL)) {
4236                 struct GUID guid;
4237                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4238                                            printer, &guid);
4239                 if (!W_ERROR_IS_OK(werr)) {
4240                         goto out_tmp_free;
4241                 }
4242                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4243                 r->action = DSPRINT_PUBLISH;
4244         } else {
4245                 r->guid = talloc_strdup(mem_ctx, "");
4246                 r->action = DSPRINT_UNPUBLISH;
4247         }
4248         if (r->guid == NULL) {
4249                 werr = WERR_NOMEM;
4250                 goto out_tmp_free;
4251         }
4252
4253         werr = WERR_OK;
4254 out_tmp_free:
4255         talloc_free(tmp_ctx);
4256         return werr;
4257 }
4258
4259 /********************************************************************
4260  * construct_printer_info8
4261  * fill a spoolss_PrinterInfo8 struct
4262  ********************************************************************/
4263
4264 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4265                                       const struct spoolss_PrinterInfo2 *info2,
4266                                       const char *servername,
4267                                       struct spoolss_DeviceModeInfo *r,
4268                                       int snum)
4269 {
4270         WERROR result;
4271         const char *printername;
4272
4273         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4274         if (!W_ERROR_IS_OK(result)) {
4275                 return result;
4276         }
4277
4278         if (info2->devmode != NULL) {
4279                 result = copy_devicemode(mem_ctx,
4280                                          info2->devmode,
4281                                          &r->devmode);
4282                 if (!W_ERROR_IS_OK(result)) {
4283                         return result;
4284                 }
4285         } else if (lp_default_devmode(snum)) {
4286                 result = spoolss_create_default_devmode(mem_ctx,
4287                                                         info2->printername,
4288                                                         &r->devmode);
4289                 if (!W_ERROR_IS_OK(result)) {
4290                         return result;
4291                 }
4292         } else {
4293                 r->devmode = NULL;
4294                 DEBUG(8,("Returning NULL Devicemode!\n"));
4295         }
4296
4297         compose_devicemode_devicename(r->devmode, printername);
4298
4299         return WERR_OK;
4300 }
4301
4302 /********************************************************************
4303  Spoolss_enumprinters.
4304 ********************************************************************/
4305
4306 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4307                                            const struct auth_session_info *session_info,
4308                                            struct messaging_context *msg_ctx,
4309                                            const char *servername,
4310                                            uint32_t level,
4311                                            uint32_t flags,
4312                                            union spoolss_PrinterInfo **info_p,
4313                                            uint32_t *count_p)
4314 {
4315         int snum;
4316         int n_services;
4317         union spoolss_PrinterInfo *info = NULL;
4318         uint32_t count = 0;
4319         WERROR result = WERR_OK;
4320         struct dcerpc_binding_handle *b = NULL;
4321         TALLOC_CTX *tmp_ctx = NULL;
4322
4323         tmp_ctx = talloc_new(mem_ctx);
4324         if (!tmp_ctx) {
4325                 return WERR_NOMEM;
4326         }
4327
4328         /*
4329          * printer shares are updated on client enumeration. The background
4330          * printer process updates printer_list.tdb at regular intervals.
4331          */
4332         become_root();
4333         delete_and_reload_printers(server_event_context(), msg_ctx);
4334         unbecome_root();
4335
4336         n_services = lp_numservices();
4337         *count_p = 0;
4338         *info_p = NULL;
4339
4340         for (snum = 0; snum < n_services; snum++) {
4341
4342                 const char *printer;
4343                 struct spoolss_PrinterInfo2 *info2;
4344
4345                 if (!snum_is_shared_printer(snum)) {
4346                         continue;
4347                 }
4348
4349                 printer = lp_const_servicename(snum);
4350
4351                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4352                         printer, snum));
4353
4354                 if (b == NULL) {
4355                         result = winreg_printer_binding_handle(tmp_ctx,
4356                                                                session_info,
4357                                                                msg_ctx,
4358                                                                &b);
4359                         if (!W_ERROR_IS_OK(result)) {
4360                                 goto out;
4361                         }
4362                 }
4363
4364                 result = winreg_create_printer(tmp_ctx, b,
4365                                                printer);
4366                 if (!W_ERROR_IS_OK(result)) {
4367                         goto out;
4368                 }
4369
4370                 info = talloc_realloc(tmp_ctx, info,
4371                                             union spoolss_PrinterInfo,
4372                                             count + 1);
4373                 if (!info) {
4374                         result = WERR_NOMEM;
4375                         goto out;
4376                 }
4377
4378                 result = winreg_get_printer(tmp_ctx, b,
4379                                             printer, &info2);
4380                 if (!W_ERROR_IS_OK(result)) {
4381                         goto out;
4382                 }
4383
4384                 switch (level) {
4385                 case 0:
4386                         result = construct_printer_info0(info, session_info,
4387                                                          msg_ctx, info2,
4388                                                          servername,
4389                                                          &info[count].info0, snum);
4390                         break;
4391                 case 1:
4392                         result = construct_printer_info1(info, info2, flags,
4393                                                          servername,
4394                                                          &info[count].info1, snum);
4395                         break;
4396                 case 2:
4397                         result = construct_printer_info2(info, msg_ctx, info2,
4398                                                          servername,
4399                                                          &info[count].info2, snum);
4400                         break;
4401                 case 4:
4402                         result = construct_printer_info4(info, info2,
4403                                                          servername,
4404                                                          &info[count].info4, snum);
4405                         break;
4406                 case 5:
4407                         result = construct_printer_info5(info, info2,
4408                                                          servername,
4409                                                          &info[count].info5, snum);
4410                         break;
4411
4412                 default:
4413                         result = WERR_UNKNOWN_LEVEL;
4414                         goto out;
4415                 }
4416
4417                 if (!W_ERROR_IS_OK(result)) {
4418                         goto out;
4419                 }
4420
4421                 count++;
4422         }
4423
4424 out:
4425         if (W_ERROR_IS_OK(result)) {
4426                 *info_p = talloc_move(mem_ctx, &info);
4427                 *count_p = count;
4428         }
4429
4430         talloc_free(tmp_ctx);
4431
4432         return result;
4433 }
4434
4435 /********************************************************************
4436  * handle enumeration of printers at level 0
4437  ********************************************************************/
4438
4439 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4440                                   const struct auth_session_info *session_info,
4441                                   struct messaging_context *msg_ctx,
4442                                   uint32_t flags,
4443                                   const char *servername,
4444                                   union spoolss_PrinterInfo **info,
4445                                   uint32_t *count)
4446 {
4447         DEBUG(4,("enum_all_printers_info_0\n"));
4448
4449         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4450                                             servername, 0, flags, info, count);
4451 }
4452
4453
4454 /********************************************************************
4455 ********************************************************************/
4456
4457 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4458                                        const struct auth_session_info *session_info,
4459                                        struct messaging_context *msg_ctx,
4460                                        const char *servername,
4461                                        uint32_t flags,
4462                                        union spoolss_PrinterInfo **info,
4463                                        uint32_t *count)
4464 {
4465         DEBUG(4,("enum_all_printers_info_1\n"));
4466
4467         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4468                                             servername, 1, flags, info, count);
4469 }
4470
4471 /********************************************************************
4472  enum_all_printers_info_1_local.
4473 *********************************************************************/
4474
4475 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4476                                              const struct auth_session_info *session_info,
4477                                              struct messaging_context *msg_ctx,
4478                                              const char *servername,
4479                                              union spoolss_PrinterInfo **info,
4480                                              uint32_t *count)
4481 {
4482         DEBUG(4,("enum_all_printers_info_1_local\n"));
4483
4484         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4485                                         servername, PRINTER_ENUM_ICON8, info, count);
4486 }
4487
4488 /********************************************************************
4489  enum_all_printers_info_1_name.
4490 *********************************************************************/
4491
4492 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4493                                             const struct auth_session_info *session_info,
4494                                             struct messaging_context *msg_ctx,
4495                                             const char *servername,
4496                                             union spoolss_PrinterInfo **info,
4497                                             uint32_t *count)
4498 {
4499         const char *s = servername;
4500
4501         DEBUG(4,("enum_all_printers_info_1_name\n"));
4502
4503         if (servername != NULL &&
4504             (servername[0] == '\\') && (servername[1] == '\\')) {
4505                 s = servername + 2;
4506         }
4507
4508         if (!is_myname_or_ipaddr(s)) {
4509                 return WERR_INVALID_NAME;
4510         }
4511
4512         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4513                                         servername, PRINTER_ENUM_ICON8, info, count);
4514 }
4515
4516 /********************************************************************
4517  enum_all_printers_info_1_network.
4518 *********************************************************************/
4519
4520 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4521                                                const struct auth_session_info *session_info,
4522                                                struct messaging_context *msg_ctx,
4523                                                const char *servername,
4524                                                union spoolss_PrinterInfo **info,
4525                                                uint32_t *count)
4526 {
4527         const char *s = servername;
4528
4529         DEBUG(4,("enum_all_printers_info_1_network\n"));
4530
4531         /* If we respond to a enum_printers level 1 on our name with flags
4532            set to PRINTER_ENUM_REMOTE with a list of printers then these
4533            printers incorrectly appear in the APW browse list.
4534            Specifically the printers for the server appear at the workgroup
4535            level where all the other servers in the domain are
4536            listed. Windows responds to this call with a
4537            WERR_CAN_NOT_COMPLETE so we should do the same. */
4538
4539         if (servername != NULL &&
4540             (servername[0] == '\\') && (servername[1] == '\\')) {
4541                  s = servername + 2;
4542         }
4543
4544         if (is_myname_or_ipaddr(s)) {
4545                  return WERR_CAN_NOT_COMPLETE;
4546         }
4547
4548         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4549                                         servername, PRINTER_ENUM_NAME, info, count);
4550 }
4551
4552 /********************************************************************
4553  * api_spoolss_enumprinters
4554  *
4555  * called from api_spoolss_enumprinters (see this to understand)
4556  ********************************************************************/
4557
4558 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4559                                        const struct auth_session_info *session_info,
4560                                        struct messaging_context *msg_ctx,
4561                                        const char *servername,
4562                                        union spoolss_PrinterInfo **info,
4563                                        uint32_t *count)
4564 {
4565         DEBUG(4,("enum_all_printers_info_2\n"));
4566
4567         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4568                                             servername, 2, 0, info, count);
4569 }
4570
4571 /********************************************************************
4572  * handle enumeration of printers at level 1
4573  ********************************************************************/
4574
4575 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4576                                   const struct auth_session_info *session_info,
4577                                   struct messaging_context *msg_ctx,
4578                                   uint32_t flags,
4579                                   const char *servername,
4580                                   union spoolss_PrinterInfo **info,
4581                                   uint32_t *count)
4582 {
4583         /* Not all the flags are equals */
4584
4585         if (flags & PRINTER_ENUM_LOCAL) {
4586                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4587                                                       msg_ctx, servername, info, count);
4588         }
4589
4590         if (flags & PRINTER_ENUM_NAME) {
4591                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4592                                                      msg_ctx, servername, info,
4593                                                      count);
4594         }
4595
4596         if (flags & PRINTER_ENUM_NETWORK) {
4597                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4598                                                         msg_ctx, servername, info,
4599                                                         count);
4600         }
4601
4602         return WERR_OK; /* NT4sp5 does that */
4603 }
4604
4605 /********************************************************************
4606  * handle enumeration of printers at level 2
4607  ********************************************************************/
4608
4609 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4610                                   const struct auth_session_info *session_info,
4611                                   struct messaging_context *msg_ctx,
4612                                   uint32_t flags,
4613                                   const char *servername,
4614                                   union spoolss_PrinterInfo **info,
4615                                   uint32_t *count)
4616 {
4617         if (flags & PRINTER_ENUM_LOCAL) {
4618
4619                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4620                                                 servername,
4621                                                 info, count);
4622         }
4623
4624         if (flags & PRINTER_ENUM_NAME) {
4625                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4626                         return WERR_INVALID_NAME;
4627                 }
4628
4629                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4630                                                 servername,
4631                                                 info, count);
4632         }
4633
4634         if (flags & PRINTER_ENUM_REMOTE) {
4635                 return WERR_UNKNOWN_LEVEL;
4636         }
4637
4638         return WERR_OK;
4639 }
4640
4641 /********************************************************************
4642  * handle enumeration of printers at level 4
4643  ********************************************************************/
4644
4645 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4646                                   const struct auth_session_info *session_info,
4647                                   struct messaging_context *msg_ctx,
4648                                   uint32_t flags,
4649                                   const char *servername,
4650                                   union spoolss_PrinterInfo **info,
4651                                   uint32_t *count)
4652 {
4653         DEBUG(4,("enum_all_printers_info_4\n"));
4654
4655         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4656                                             servername, 4, flags, info, count);
4657 }
4658
4659
4660 /********************************************************************
4661  * handle enumeration of printers at level 5
4662  ********************************************************************/
4663
4664 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4665                                   const struct auth_session_info *session_info,
4666                                   struct messaging_context *msg_ctx,
4667                                   uint32_t flags,
4668                                   const char *servername,
4669                                   union spoolss_PrinterInfo **info,
4670                                   uint32_t *count)
4671 {
4672         DEBUG(4,("enum_all_printers_info_5\n"));
4673
4674         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4675                                             servername, 5, flags, info, count);
4676 }
4677
4678 /****************************************************************
4679  _spoolss_EnumPrinters
4680 ****************************************************************/
4681
4682 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4683                              struct spoolss_EnumPrinters *r)
4684 {
4685         const struct auth_session_info *session_info = get_session_info_system();
4686         WERROR result;
4687
4688         /* that's an [in out] buffer */
4689
4690         if (!r->in.buffer && (r->in.offered != 0)) {
4691                 return WERR_INVALID_PARAM;
4692         }
4693
4694         DEBUG(4,("_spoolss_EnumPrinters\n"));
4695
4696         *r->out.needed = 0;
4697         *r->out.count = 0;
4698         *r->out.info = NULL;
4699
4700         /*
4701          * Level 1:
4702          *          flags==PRINTER_ENUM_NAME
4703          *           if name=="" then enumerates all printers
4704          *           if name!="" then enumerate the printer
4705          *          flags==PRINTER_ENUM_REMOTE
4706          *          name is NULL, enumerate printers
4707          * Level 2: name!="" enumerates printers, name can't be NULL
4708          * Level 3: doesn't exist
4709          * Level 4: does a local registry lookup
4710          * Level 5: same as Level 2
4711          */
4712
4713         if (r->in.server && r->in.server[0] == '\0') {
4714                 r->in.server = NULL;
4715         }
4716
4717         switch (r->in.level) {
4718         case 0:
4719                 result = enumprinters_level0(p->mem_ctx, session_info,
4720                                              p->msg_ctx, r->in.flags,
4721                                              r->in.server,
4722                                              r->out.info, r->out.count);
4723                 break;
4724         case 1:
4725                 result = enumprinters_level1(p->mem_ctx, session_info,
4726                                              p->msg_ctx, r->in.flags,
4727                                              r->in.server,
4728                                              r->out.info, r->out.count);
4729                 break;
4730         case 2:
4731                 result = enumprinters_level2(p->mem_ctx, session_info,
4732                                              p->msg_ctx, r->in.flags,
4733                                              r->in.server,
4734                                              r->out.info, r->out.count);
4735                 break;
4736         case 4:
4737                 result = enumprinters_level4(p->mem_ctx, session_info,
4738                                              p->msg_ctx, r->in.flags,
4739                                              r->in.server,
4740                                              r->out.info, r->out.count);
4741                 break;
4742         case 5:
4743                 result = enumprinters_level5(p->mem_ctx, session_info,
4744                                              p->msg_ctx, r->in.flags,
4745                                              r->in.server,
4746                                              r->out.info, r->out.count);
4747                 break;
4748         default:
4749                 return WERR_UNKNOWN_LEVEL;
4750         }
4751
4752         if (!W_ERROR_IS_OK(result)) {
4753                 return result;
4754         }
4755
4756         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4757                                                      spoolss_EnumPrinters,
4758                                                      *r->out.info, r->in.level,
4759                                                      *r->out.count);
4760         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4761         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4762
4763         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4764 }
4765
4766 /****************************************************************
4767  _spoolss_GetPrinter
4768 ****************************************************************/
4769
4770 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4771                            struct spoolss_GetPrinter *r)
4772 {
4773         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4774         struct spoolss_PrinterInfo2 *info2 = NULL;
4775         WERROR result = WERR_OK;
4776         int snum;
4777
4778         /* that's an [in out] buffer */
4779
4780         if (!r->in.buffer && (r->in.offered != 0)) {
4781                 result = WERR_INVALID_PARAM;
4782                 goto err_info_free;
4783         }
4784
4785         *r->out.needed = 0;
4786
4787         if (Printer == NULL) {
4788                 result = WERR_BADFID;
4789                 goto err_info_free;
4790         }
4791
4792         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4793                 result = WERR_BADFID;
4794                 goto err_info_free;
4795         }
4796
4797         result = winreg_get_printer_internal(p->mem_ctx,
4798                                     get_session_info_system(),
4799                                     p->msg_ctx,
4800                                     lp_const_servicename(snum),
4801                                     &info2);
4802         if (!W_ERROR_IS_OK(result)) {
4803                 goto err_info_free;
4804         }
4805
4806         switch (r->in.level) {
4807         case 0:
4808                 result = construct_printer_info0(p->mem_ctx,
4809                                                  get_session_info_system(),
4810                                                  p->msg_ctx,
4811                                                  info2,
4812                                                  Printer->servername,
4813                                                  &r->out.info->info0,
4814                                                  snum);
4815                 break;
4816         case 1:
4817                 result = construct_printer_info1(p->mem_ctx, info2,
4818                                                  PRINTER_ENUM_ICON8,
4819                                                  Printer->servername,
4820                                                  &r->out.info->info1, snum);
4821                 break;
4822         case 2:
4823                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4824                                                  Printer->servername,
4825                                                  &r->out.info->info2, snum);
4826                 break;
4827         case 3:
4828                 result = construct_printer_info3(p->mem_ctx, info2,
4829                                                  Printer->servername,
4830                                                  &r->out.info->info3, snum);
4831                 break;
4832         case 4:
4833                 result = construct_printer_info4(p->mem_ctx, info2,
4834                                                  Printer->servername,
4835                                                  &r->out.info->info4, snum);
4836                 break;
4837         case 5:
4838                 result = construct_printer_info5(p->mem_ctx, info2,
4839                                                  Printer->servername,
4840                                                  &r->out.info->info5, snum);
4841                 break;
4842         case 6:
4843                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4844                                                  Printer->servername,
4845                                                  &r->out.info->info6, snum);
4846                 break;
4847         case 7:
4848                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4849                                                  Printer->servername,
4850                                                  &r->out.info->info7, snum);
4851                 break;
4852         case 8:
4853                 result = construct_printer_info8(p->mem_ctx, info2,
4854                                                  Printer->servername,
4855                                                  &r->out.info->info8, snum);
4856                 break;
4857         default:
4858                 result = WERR_UNKNOWN_LEVEL;
4859                 break;
4860         }
4861         TALLOC_FREE(info2);
4862
4863         if (!W_ERROR_IS_OK(result)) {
4864                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4865                           r->in.level, win_errstr(result)));
4866                 goto err_info_free;
4867         }
4868
4869         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4870                                                r->out.info, r->in.level);
4871         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4872
4873         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4874
4875 err_info_free:
4876         TALLOC_FREE(r->out.info);
4877         return result;
4878 }
4879
4880 /********************************************************************
4881  ********************************************************************/
4882
4883 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4884         do { \
4885                 if (in && strlen(in)) { \
4886                         out = talloc_strdup(mem_ctx, in); \
4887                 } else { \
4888                         out = talloc_strdup(mem_ctx, ""); \
4889                 } \
4890                 W_ERROR_HAVE_NO_MEMORY(out); \
4891         } while (0);
4892
4893 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4894         do { \
4895                 if (in && strlen(in)) { \
4896                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4897                 } else { \
4898                         out = talloc_strdup(mem_ctx, ""); \
4899                 } \
4900                 W_ERROR_HAVE_NO_MEMORY(out); \
4901         } while (0);
4902
4903 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4904                                                   const char **string_array,
4905                                                   const char ***presult,
4906                                                   const char *cservername,
4907                                                   const char *arch,
4908                                                   int version)
4909 {
4910         int i;
4911         size_t num_strings = 0;
4912         const char **array = NULL;
4913
4914         if (string_array == NULL) {
4915                 return WERR_INVALID_PARAMETER;
4916         }
4917
4918         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4919                 const char *str = NULL;
4920
4921                 if (cservername == NULL || arch == NULL) {
4922                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4923                 } else {
4924                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4925                 }
4926
4927                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4928                         TALLOC_FREE(array);
4929                         return WERR_NOMEM;
4930                 }
4931         }
4932
4933         if (i > 0) {
4934                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4935                              &array, &num_strings);
4936         }
4937
4938         if (presult != NULL) {
4939                 *presult = array;
4940         } else {
4941                 talloc_free(array);
4942         }
4943
4944         return WERR_OK;
4945 }
4946
4947 /********************************************************************
4948  * fill a spoolss_DriverInfo1 struct
4949  ********************************************************************/
4950
4951 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4952                                         struct spoolss_DriverInfo1 *r,
4953                                         const struct spoolss_DriverInfo8 *driver,
4954                                         const char *servername)
4955 {
4956         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4957         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4958
4959         return WERR_OK;
4960 }
4961
4962 /********************************************************************
4963  * fill a spoolss_DriverInfo2 struct
4964  ********************************************************************/
4965
4966 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4967                                         struct spoolss_DriverInfo2 *r,
4968                                         const struct spoolss_DriverInfo8 *driver,
4969                                         const char *servername)
4970
4971 {
4972         const char *cservername = canon_servername(servername);
4973
4974         r->version              = driver->version;
4975
4976         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4977         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4978         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4979         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4980
4981         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4982                                driver->architecture,
4983                                driver->version,
4984                                driver->driver_path,
4985                                r->driver_path);
4986
4987         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4988                                driver->architecture,
4989                                driver->version,
4990                                driver->data_file,
4991                                r->data_file);
4992
4993         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4994                                driver->architecture,
4995                                driver->version,
4996                                driver->config_file,
4997                                r->config_file);
4998
4999         return WERR_OK;
5000 }
5001
5002 /********************************************************************
5003  * fill a spoolss_DriverInfo3 struct
5004  ********************************************************************/
5005
5006 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5007                                         struct spoolss_DriverInfo3 *r,
5008                                         const struct spoolss_DriverInfo8 *driver,
5009                                         const char *servername)
5010 {
5011         const char *cservername = canon_servername(servername);
5012
5013         r->version              = driver->version;
5014
5015         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5016         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5017         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5018         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5019
5020         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5021                                driver->architecture,
5022                                driver->version,
5023                                driver->driver_path,
5024                                r->driver_path);
5025
5026         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5027                                driver->architecture,
5028                                driver->version,
5029                                driver->data_file,
5030                                r->data_file);
5031
5032         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5033                                driver->architecture,
5034                                driver->version,
5035                                driver->config_file,
5036                                r->config_file);
5037
5038         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5039                                driver->architecture,
5040                                driver->version,
5041                                driver->help_file,
5042                                r->help_file);
5043
5044         FILL_DRIVER_STRING(mem_ctx,
5045                            driver->monitor_name,
5046                            r->monitor_name);
5047
5048         FILL_DRIVER_STRING(mem_ctx,
5049                            driver->default_datatype,
5050                            r->default_datatype);
5051
5052         return string_array_from_driver_info(mem_ctx,
5053                                              driver->dependent_files,
5054                                              &r->dependent_files,
5055                                              cservername,
5056                                              driver->architecture,
5057                                              driver->version);
5058 }
5059
5060 /********************************************************************
5061  * fill a spoolss_DriverInfo4 struct
5062  ********************************************************************/
5063
5064 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5065                                         struct spoolss_DriverInfo4 *r,
5066                                         const struct spoolss_DriverInfo8 *driver,
5067                                         const char *servername)
5068 {
5069         const char *cservername = canon_servername(servername);
5070         WERROR result;
5071
5072         r->version              = driver->version;
5073
5074         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5075         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5076         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5077         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5078
5079         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5080                                driver->architecture,
5081                                driver->version,
5082                                driver->driver_path,
5083                                r->driver_path);
5084
5085         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5086                                driver->architecture,
5087                                driver->version,
5088                                driver->data_file,
5089                                r->data_file);
5090
5091         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5092                                driver->architecture,
5093                                driver->version,
5094                                driver->config_file,
5095                                r->config_file);
5096
5097         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5098                                driver->architecture,
5099                                driver->version,
5100                                driver->help_file,
5101                                r->help_file);
5102
5103         result = string_array_from_driver_info(mem_ctx,
5104                                                driver->dependent_files,
5105                                                &r->dependent_files,
5106                                                cservername,
5107                                                driver->architecture,
5108                                                driver->version);
5109         if (!W_ERROR_IS_OK(result)) {
5110                 return result;
5111         }
5112
5113         FILL_DRIVER_STRING(mem_ctx,
5114                            driver->monitor_name,
5115                            r->monitor_name);
5116
5117         FILL_DRIVER_STRING(mem_ctx,
5118                            driver->default_datatype,
5119                            r->default_datatype);
5120
5121
5122         result = string_array_from_driver_info(mem_ctx,
5123                                                driver->previous_names,
5124                                                &r->previous_names,
5125                                                NULL, NULL, 0);
5126
5127         return result;
5128 }
5129
5130 /********************************************************************
5131  * fill a spoolss_DriverInfo5 struct
5132  ********************************************************************/
5133
5134 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5135                                         struct spoolss_DriverInfo5 *r,
5136                                         const struct spoolss_DriverInfo8 *driver,
5137                                         const char *servername)
5138 {
5139         const char *cservername = canon_servername(servername);
5140
5141         r->version              = driver->version;
5142
5143         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5144         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5145         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5146         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5147
5148         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5149                                driver->architecture,
5150                                driver->version,
5151                                driver->driver_path,
5152                                r->driver_path);
5153
5154         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5155                                driver->architecture,
5156                                driver->version,
5157                                driver->data_file,
5158                                r->data_file);
5159
5160         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5161                                driver->architecture,
5162                                driver->version,
5163                                driver->config_file,
5164                                r->config_file);
5165
5166         r->driver_attributes    = 0;
5167         r->config_version       = 0;
5168         r->driver_version       = 0;
5169
5170         return WERR_OK;
5171 }
5172 /********************************************************************
5173  * fill a spoolss_DriverInfo6 struct
5174  ********************************************************************/
5175
5176 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5177                                         struct spoolss_DriverInfo6 *r,
5178                                         const struct spoolss_DriverInfo8 *driver,
5179                                         const char *servername)
5180 {
5181         const char *cservername = canon_servername(servername);
5182         WERROR result;
5183
5184         r->version              = driver->version;
5185
5186         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5187         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5188         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5189         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5190
5191         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5192                                driver->architecture,
5193                                driver->version,
5194                                driver->driver_path,
5195                                r->driver_path);
5196
5197         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5198                                driver->architecture,
5199                                driver->version,
5200                                driver->data_file,
5201                                r->data_file);
5202
5203         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5204                                driver->architecture,
5205                                driver->version,
5206                                driver->config_file,
5207                                r->config_file);
5208
5209         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5210                                driver->architecture,
5211                                driver->version,
5212                                driver->help_file,
5213                                r->help_file);
5214
5215         FILL_DRIVER_STRING(mem_ctx,
5216                            driver->monitor_name,
5217                            r->monitor_name);
5218
5219         FILL_DRIVER_STRING(mem_ctx,
5220                            driver->default_datatype,
5221                            r->default_datatype);
5222
5223         result = string_array_from_driver_info(mem_ctx,
5224                                                driver->dependent_files,
5225                                                &r->dependent_files,
5226                                                cservername,
5227                                                driver->architecture,
5228                                                driver->version);
5229         if (!W_ERROR_IS_OK(result)) {
5230                 return result;
5231         }
5232
5233         result = string_array_from_driver_info(mem_ctx,
5234                                                driver->previous_names,
5235                                                &r->previous_names,
5236                                                NULL, NULL, 0);
5237         if (!W_ERROR_IS_OK(result)) {
5238                 return result;
5239         }
5240
5241         r->driver_date          = driver->driver_date;
5242         r->driver_version       = driver->driver_version;
5243
5244         FILL_DRIVER_STRING(mem_ctx,
5245                            driver->manufacturer_name,
5246                            r->manufacturer_name);
5247         FILL_DRIVER_STRING(mem_ctx,
5248                            driver->manufacturer_url,
5249                            r->manufacturer_url);
5250         FILL_DRIVER_STRING(mem_ctx,
5251                            driver->hardware_id,
5252                            r->hardware_id);
5253         FILL_DRIVER_STRING(mem_ctx,
5254                            driver->provider,
5255                            r->provider);
5256
5257         return WERR_OK;
5258 }
5259
5260 /********************************************************************
5261  * fill a spoolss_DriverInfo8 struct
5262  ********************************************************************/
5263
5264 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5265                                         struct spoolss_DriverInfo8 *r,
5266                                         const struct spoolss_DriverInfo8 *driver,
5267                                         const char *servername)
5268 {
5269         const char *cservername = canon_servername(servername);
5270         WERROR result;
5271
5272         r->version              = driver->version;
5273
5274         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5275         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5276         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5277         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5278
5279         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5280                                driver->architecture,
5281                                driver->version,
5282                                driver->driver_path,
5283                                r->driver_path);
5284
5285         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5286                                driver->architecture,
5287                                driver->version,
5288                                driver->data_file,
5289                                r->data_file);
5290
5291         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5292                                driver->architecture,
5293                                driver->version,
5294                                driver->config_file,
5295                                r->config_file);
5296
5297         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5298                                driver->architecture,
5299                                driver->version,
5300                                driver->help_file,
5301                                r->help_file);
5302
5303         FILL_DRIVER_STRING(mem_ctx,
5304                            driver->monitor_name,
5305                            r->monitor_name);
5306
5307         FILL_DRIVER_STRING(mem_ctx,
5308                            driver->default_datatype,
5309                            r->default_datatype);
5310
5311         result = string_array_from_driver_info(mem_ctx,
5312                                                driver->dependent_files,
5313                                                &r->dependent_files,
5314                                                cservername,
5315                                                driver->architecture,
5316                                                driver->version);
5317         if (!W_ERROR_IS_OK(result)) {
5318                 return result;
5319         }
5320
5321         result = string_array_from_driver_info(mem_ctx,
5322                                                driver->previous_names,
5323                                                &r->previous_names,
5324                                                NULL, NULL, 0);
5325         if (!W_ERROR_IS_OK(result)) {
5326                 return result;
5327         }
5328
5329         r->driver_date          = driver->driver_date;
5330         r->driver_version       = driver->driver_version;
5331
5332         FILL_DRIVER_STRING(mem_ctx,
5333                            driver->manufacturer_name,
5334                            r->manufacturer_name);
5335         FILL_DRIVER_STRING(mem_ctx,
5336                            driver->manufacturer_url,
5337                            r->manufacturer_url);
5338         FILL_DRIVER_STRING(mem_ctx,
5339                            driver->hardware_id,
5340                            r->hardware_id);
5341         FILL_DRIVER_STRING(mem_ctx,
5342                            driver->provider,
5343                            r->provider);
5344
5345         FILL_DRIVER_STRING(mem_ctx,
5346                            driver->print_processor,
5347                            r->print_processor);
5348         FILL_DRIVER_STRING(mem_ctx,
5349                            driver->vendor_setup,
5350                            r->vendor_setup);
5351
5352         result = string_array_from_driver_info(mem_ctx,
5353                                                driver->color_profiles,
5354                                                &r->color_profiles,
5355                                                NULL, NULL, 0);
5356         if (!W_ERROR_IS_OK(result)) {
5357                 return result;
5358         }
5359
5360         FILL_DRIVER_STRING(mem_ctx,
5361                            driver->inf_path,
5362                            r->inf_path);
5363
5364         r->printer_driver_attributes    = driver->printer_driver_attributes;
5365
5366         result = string_array_from_driver_info(mem_ctx,
5367                                                driver->core_driver_dependencies,
5368                                                &r->core_driver_dependencies,
5369                                                NULL, NULL, 0);
5370         if (!W_ERROR_IS_OK(result)) {
5371                 return result;
5372         }
5373
5374         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5375         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5376
5377         return WERR_OK;
5378 }
5379
5380 #if 0 /* disabled until marshalling issues are resolved - gd */
5381 /********************************************************************
5382  ********************************************************************/
5383
5384 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5385                                           struct spoolss_DriverFileInfo *r,
5386                                           const char *cservername,
5387                                           const char *file_name,
5388                                           enum spoolss_DriverFileType file_type,
5389                                           uint32_t file_version)
5390 {
5391         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5392                                           cservername, file_name);
5393         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5394         r->file_type    = file_type;
5395         r->file_version = file_version;
5396
5397         return WERR_OK;
5398 }
5399
5400 /********************************************************************
5401  ********************************************************************/
5402
5403 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5404                                                  const struct spoolss_DriverInfo8 *driver,
5405                                                  const char *cservername,
5406                                                  struct spoolss_DriverFileInfo **info_p,
5407                                                  uint32_t *count_p)
5408 {
5409         struct spoolss_DriverFileInfo *info = NULL;
5410         uint32_t count = 0;
5411         WERROR result;
5412         uint32_t i;
5413
5414         *info_p = NULL;
5415         *count_p = 0;
5416
5417         if (strlen(driver->driver_path)) {
5418                 info = talloc_realloc(mem_ctx, info,
5419                                             struct spoolss_DriverFileInfo,
5420                                             count + 1);
5421                 W_ERROR_HAVE_NO_MEMORY(info);
5422                 result = fill_spoolss_DriverFileInfo(info,
5423                                                      &info[count],
5424                                                      cservername,
5425                                                      driver->driver_path,
5426                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5427                                                      0);
5428                 W_ERROR_NOT_OK_RETURN(result);
5429                 count++;
5430         }
5431
5432         if (strlen(driver->config_file)) {
5433                 info = talloc_realloc(mem_ctx, info,
5434                                             struct spoolss_DriverFileInfo,
5435                                             count + 1);
5436                 W_ERROR_HAVE_NO_MEMORY(info);
5437                 result = fill_spoolss_DriverFileInfo(info,
5438                                                      &info[count],
5439                                                      cservername,
5440                                                      driver->config_file,
5441                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5442                                                      0);
5443                 W_ERROR_NOT_OK_RETURN(result);
5444                 count++;
5445         }
5446
5447         if (strlen(driver->data_file)) {
5448                 info = talloc_realloc(mem_ctx, info,
5449                                             struct spoolss_DriverFileInfo,
5450                                             count + 1);
5451                 W_ERROR_HAVE_NO_MEMORY(info);
5452                 result = fill_spoolss_DriverFileInfo(info,
5453                                                      &info[count],
5454                                                      cservername,
5455                                                      driver->data_file,
5456                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5457                                                      0);
5458                 W_ERROR_NOT_OK_RETURN(result);
5459                 count++;
5460         }
5461
5462         if (strlen(driver->help_file)) {
5463                 info = talloc_realloc(mem_ctx, info,
5464                                             struct spoolss_DriverFileInfo,
5465                                             count + 1);
5466                 W_ERROR_HAVE_NO_MEMORY(info);
5467                 result = fill_spoolss_DriverFileInfo(info,
5468                                                      &info[count],
5469                                                      cservername,
5470                                                      driver->help_file,
5471                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5472                                                      0);
5473                 W_ERROR_NOT_OK_RETURN(result);
5474                 count++;
5475         }
5476
5477         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5478                 info = talloc_realloc(mem_ctx, info,
5479                                             struct spoolss_DriverFileInfo,
5480                                             count + 1);
5481                 W_ERROR_HAVE_NO_MEMORY(info);
5482                 result = fill_spoolss_DriverFileInfo(info,
5483                                                      &info[count],
5484                                                      cservername,
5485                                                      driver->dependent_files[i],
5486                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5487                                                      0);
5488                 W_ERROR_NOT_OK_RETURN(result);
5489                 count++;
5490         }
5491
5492         *info_p = info;
5493         *count_p = count;
5494
5495         return WERR_OK;
5496 }
5497
5498 /********************************************************************
5499  * fill a spoolss_DriverInfo101 struct
5500  ********************************************************************/
5501
5502 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5503                                           struct spoolss_DriverInfo101 *r,
5504                                           const struct spoolss_DriverInfo8 *driver,
5505                                           const char *servername)
5506 {
5507         const char *cservername = canon_servername(servername);
5508         WERROR result;
5509
5510         r->version              = driver->version;
5511
5512         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5513         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5514         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5515         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5516
5517         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5518                                                     cservername,
5519                                                     &r->file_info,
5520                                                     &r->file_count);
5521         if (!W_ERROR_IS_OK(result)) {
5522                 return result;
5523         }
5524
5525         FILL_DRIVER_STRING(mem_ctx,
5526                            driver->monitor_name,
5527                            r->monitor_name);
5528
5529         FILL_DRIVER_STRING(mem_ctx,
5530                            driver->default_datatype,
5531                            r->default_datatype);
5532
5533         result = string_array_from_driver_info(mem_ctx,
5534                                                driver->previous_names,
5535                                                &r->previous_names,
5536                                                NULL, NULL, 0);
5537         if (!W_ERROR_IS_OK(result)) {
5538                 return result;
5539         }
5540
5541         r->driver_date          = driver->driver_date;
5542         r->driver_version       = driver->driver_version;
5543
5544         FILL_DRIVER_STRING(mem_ctx,
5545                            driver->manufacturer_name,
5546                            r->manufacturer_name);
5547         FILL_DRIVER_STRING(mem_ctx,
5548                            driver->manufacturer_url,
5549                            r->manufacturer_url);
5550         FILL_DRIVER_STRING(mem_ctx,
5551                            driver->hardware_id,
5552                            r->hardware_id);
5553         FILL_DRIVER_STRING(mem_ctx,
5554                            driver->provider,
5555                            r->provider);
5556
5557         return WERR_OK;
5558 }
5559 #endif
5560 /********************************************************************
5561  ********************************************************************/
5562
5563 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5564                                                   const struct auth_session_info *session_info,
5565                                                   struct messaging_context *msg_ctx,
5566                                                   uint32_t level,
5567                                                   union spoolss_DriverInfo *r,
5568                                                   int snum,
5569                                                   const char *servername,
5570                                                   const char *architecture,
5571                                                   uint32_t version)
5572 {
5573         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5574         struct spoolss_DriverInfo8 *driver;
5575         WERROR result;
5576         struct dcerpc_binding_handle *b;
5577         TALLOC_CTX *tmp_ctx = NULL;
5578
5579         if (level == 101) {
5580                 return WERR_UNKNOWN_LEVEL;
5581         }
5582
5583         tmp_ctx = talloc_new(mem_ctx);
5584         if (!tmp_ctx) {
5585                 return WERR_NOMEM;
5586         }
5587
5588         result = winreg_printer_binding_handle(tmp_ctx,
5589                                                session_info,
5590                                                msg_ctx,
5591                                                &b);
5592         if (!W_ERROR_IS_OK(result)) {
5593                 goto done;
5594         }
5595
5596         result = winreg_get_printer(tmp_ctx, b,
5597                                     lp_const_servicename(snum),
5598                                     &pinfo2);
5599
5600         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5601                 win_errstr(result)));
5602
5603         if (!W_ERROR_IS_OK(result)) {
5604                 result = WERR_INVALID_PRINTER_NAME;
5605                 goto done;
5606         }
5607
5608         result = winreg_get_driver(tmp_ctx, b,
5609                                    architecture,
5610                                    pinfo2->drivername, version, &driver);
5611
5612         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5613                 win_errstr(result)));
5614
5615         if (!W_ERROR_IS_OK(result)) {
5616                 /*
5617                  * Is this a W2k client ?
5618                  */
5619
5620                 if (version < 3) {
5621                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5622                         goto done;
5623                 }
5624
5625                 /* Yes - try again with a WinNT driver. */
5626                 version = 2;
5627                 result = winreg_get_driver(tmp_ctx, b,
5628                                            architecture,
5629                                            pinfo2->drivername,
5630                                            version, &driver);
5631                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5632                         win_errstr(result)));
5633                 if (!W_ERROR_IS_OK(result)) {
5634                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5635                         goto done;
5636                 }
5637         }
5638
5639         /* these are allocated on mem_ctx and not tmp_ctx because they are
5640          * the 'return value' and need to utlive this call */
5641         switch (level) {
5642         case 1:
5643                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5644                 break;
5645         case 2:
5646                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5647                 break;
5648         case 3:
5649                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5650                 break;
5651         case 4:
5652                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5653                 break;
5654         case 5:
5655                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5656                 break;
5657         case 6:
5658                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5659                 break;
5660         case 8:
5661                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5662                 break;
5663 #if 0 /* disabled until marshalling issues are resolved - gd */
5664         case 101:
5665                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5666                 break;
5667 #endif
5668         default:
5669                 result = WERR_UNKNOWN_LEVEL;
5670                 break;
5671         }
5672
5673 done:
5674         talloc_free(tmp_ctx);
5675         return result;
5676 }
5677
5678 /****************************************************************
5679  _spoolss_GetPrinterDriver2
5680 ****************************************************************/
5681
5682 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5683                                   struct spoolss_GetPrinterDriver2 *r)
5684 {
5685         struct printer_handle *printer;
5686         WERROR result;
5687         uint32_t version = r->in.client_major_version;
5688
5689         int snum;
5690
5691         /* that's an [in out] buffer */
5692
5693         if (!r->in.buffer && (r->in.offered != 0)) {
5694                 result = WERR_INVALID_PARAM;
5695                 goto err_info_free;
5696         }
5697
5698         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5699
5700         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5701                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5702                 result = WERR_INVALID_PRINTER_NAME;
5703                 goto err_info_free;
5704         }
5705
5706         *r->out.needed = 0;
5707         *r->out.server_major_version = 0;
5708         *r->out.server_minor_version = 0;
5709
5710         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5711                 result = WERR_BADFID;
5712                 goto err_info_free;
5713         }
5714
5715         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5716                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5717                         "downgrading to v3\n"));
5718                 version = SPOOLSS_DRIVER_VERSION_200X;
5719         }
5720
5721         result = construct_printer_driver_info_level(p->mem_ctx,
5722                                                      get_session_info_system(),
5723                                                      p->msg_ctx,
5724                                                      r->in.level, r->out.info,
5725                                                      snum, printer->servername,
5726                                                      r->in.architecture,
5727                                                      version);
5728         if (!W_ERROR_IS_OK(result)) {
5729                 goto err_info_free;
5730         }
5731
5732         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5733                                                r->out.info, r->in.level);
5734         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5735
5736         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5737
5738 err_info_free:
5739         TALLOC_FREE(r->out.info);
5740         return result;
5741 }
5742
5743
5744 /****************************************************************
5745  _spoolss_StartPagePrinter
5746 ****************************************************************/
5747
5748 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5749                                  struct spoolss_StartPagePrinter *r)
5750 {
5751         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5752
5753         if (!Printer) {
5754                 DEBUG(3,("_spoolss_StartPagePrinter: "
5755                         "Error in startpageprinter printer handle\n"));
5756                 return WERR_BADFID;
5757         }
5758
5759         Printer->page_started = true;
5760         return WERR_OK;
5761 }
5762
5763 /****************************************************************
5764  _spoolss_EndPagePrinter
5765 ****************************************************************/
5766
5767 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5768                                struct spoolss_EndPagePrinter *r)
5769 {
5770         int snum;
5771
5772         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5773
5774         if (!Printer) {
5775                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5776                         OUR_HANDLE(r->in.handle)));
5777                 return WERR_BADFID;
5778         }
5779
5780         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5781                 return WERR_BADFID;
5782
5783         Printer->page_started = false;
5784         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5785
5786         return WERR_OK;
5787 }
5788
5789 /****************************************************************
5790  _spoolss_StartDocPrinter
5791 ****************************************************************/
5792
5793 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5794                                 struct spoolss_StartDocPrinter *r)
5795 {
5796         struct spoolss_DocumentInfo1 *info_1;
5797         int snum;
5798         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5799         WERROR werr;
5800         char *rhost;
5801         int rc;
5802
5803         if (!Printer) {
5804                 DEBUG(2,("_spoolss_StartDocPrinter: "
5805                         "Invalid handle (%s:%u:%u)\n",
5806                         OUR_HANDLE(r->in.handle)));
5807                 return WERR_BADFID;
5808         }
5809
5810         if (Printer->jobid) {
5811                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5812                           "StartDocPrinter called twice! "
5813                           "(existing jobid = %d)\n", Printer->jobid));
5814                 return WERR_INVALID_HANDLE;
5815         }
5816
5817         if (r->in.info_ctr->level != 1) {
5818                 return WERR_UNKNOWN_LEVEL;
5819         }
5820
5821         info_1 = r->in.info_ctr->info.info1;
5822
5823         /*
5824          * a nice thing with NT is it doesn't listen to what you tell it.
5825          * when asked to send _only_ RAW datas, it tries to send datas
5826          * in EMF format.
5827          *
5828          * So I add checks like in NT Server ...
5829          */
5830
5831         if (info_1->datatype) {
5832                 /*
5833                  * The v4 driver model used in Windows 8 declares print jobs
5834                  * intended to bypass the XPS processing layer by setting
5835                  * datatype to "XPS_PASS" instead of "RAW".
5836                  */
5837                 if ((strcmp(info_1->datatype, "RAW") != 0)
5838                  && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5839                         *r->out.job_id = 0;
5840                         return WERR_INVALID_DATATYPE;
5841                 }
5842         }
5843
5844         /* get the share number of the printer */
5845         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5846                 return WERR_BADFID;
5847         }
5848
5849         rc = get_remote_hostname(p->remote_address,
5850                                  &rhost,
5851                                  p->mem_ctx);
5852         if (rc < 0) {
5853                 return WERR_NOMEM;
5854         }
5855         if (strequal(rhost,"UNKNOWN")) {
5856                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5857                                                          p->mem_ctx);
5858                 if (rhost == NULL) {
5859                         return WERR_NOMEM;
5860                 }
5861         }
5862
5863         werr = print_job_start(p->session_info,
5864                                p->msg_ctx,
5865                                rhost,
5866                                snum,
5867                                info_1->document_name,
5868                                info_1->output_file,
5869                                Printer->devmode,
5870                                &Printer->jobid);
5871
5872         /* An error occured in print_job_start() so return an appropriate
5873            NT error code. */
5874
5875         if (!W_ERROR_IS_OK(werr)) {
5876                 return werr;
5877         }
5878
5879         Printer->document_started = true;
5880         *r->out.job_id = Printer->jobid;
5881
5882         return WERR_OK;
5883 }
5884
5885 /****************************************************************
5886  _spoolss_EndDocPrinter
5887 ****************************************************************/
5888
5889 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5890                               struct spoolss_EndDocPrinter *r)
5891 {
5892         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5893         NTSTATUS status;
5894         int snum;
5895
5896         if (!Printer) {
5897                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5898                         OUR_HANDLE(r->in.handle)));
5899                 return WERR_BADFID;
5900         }
5901
5902         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5903                 return WERR_BADFID;
5904         }
5905
5906         Printer->document_started = false;
5907         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5908         if (!NT_STATUS_IS_OK(status)) {
5909                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5910                           "print_job_end failed [%s]\n",
5911                           nt_errstr(status)));
5912         }
5913
5914         Printer->jobid = 0;
5915         return ntstatus_to_werror(status);
5916 }
5917
5918 /****************************************************************
5919  _spoolss_WritePrinter
5920 ****************************************************************/
5921
5922 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5923                              struct spoolss_WritePrinter *r)
5924 {
5925         ssize_t buffer_written;
5926         int snum;
5927         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5928
5929         if (!Printer) {
5930                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5931                         OUR_HANDLE(r->in.handle)));
5932                 *r->out.num_written = r->in._data_size;
5933                 return WERR_BADFID;
5934         }
5935
5936         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5937                 return WERR_BADFID;
5938
5939         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5940         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5941                                                    snum, Printer->jobid,
5942                                                    (const char *)r->in.data.data,
5943                                                    (size_t)r->in._data_size);
5944         if (buffer_written == (ssize_t)-1) {
5945                 *r->out.num_written = 0;
5946                 if (errno == ENOSPC)
5947                         return WERR_NO_SPOOL_SPACE;
5948                 else
5949                         return WERR_ACCESS_DENIED;
5950         }
5951
5952         *r->out.num_written = r->in._data_size;
5953
5954         return WERR_OK;
5955 }
5956
5957 /********************************************************************
5958  * api_spoolss_getprinter
5959  * called from the spoolss dispatcher
5960  *
5961  ********************************************************************/
5962
5963 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5964                               struct pipes_struct *p)
5965 {
5966         const struct auth_session_info *session_info = p->session_info;
5967         int snum;
5968         WERROR errcode = WERR_BADFUNC;
5969         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5970
5971         if (!Printer) {
5972                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5973                         OUR_HANDLE(handle)));
5974                 return WERR_BADFID;
5975         }
5976
5977         if (!get_printer_snum(p, handle, &snum, NULL))
5978                 return WERR_BADFID;
5979
5980         switch (command) {
5981         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5982                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5983                 break;
5984         case SPOOLSS_PRINTER_CONTROL_RESUME:
5985         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5986                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5987                 break;
5988         case SPOOLSS_PRINTER_CONTROL_PURGE:
5989                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5990                 break;
5991         default:
5992                 return WERR_UNKNOWN_LEVEL;
5993         }
5994
5995         return errcode;
5996 }
5997
5998
5999 /****************************************************************
6000  _spoolss_AbortPrinter
6001  * From MSDN: "Deletes printer's spool file if printer is configured
6002  * for spooling"
6003 ****************************************************************/
6004
6005 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6006                              struct spoolss_AbortPrinter *r)
6007 {
6008         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
6009         int             snum;
6010         WERROR          errcode = WERR_OK;
6011
6012         if (!Printer) {
6013                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6014                         OUR_HANDLE(r->in.handle)));
6015                 return WERR_BADFID;
6016         }
6017
6018         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6019                 return WERR_BADFID;
6020
6021         if (!Printer->document_started) {
6022                 return WERR_SPL_NO_STARTDOC;
6023         }
6024
6025         errcode = print_job_delete(p->session_info,
6026                                    p->msg_ctx,
6027                                    snum,
6028                                    Printer->jobid);
6029
6030         return errcode;
6031 }
6032
6033 /********************************************************************
6034  * called by spoolss_api_setprinter
6035  * when updating a printer description
6036  ********************************************************************/
6037
6038 static WERROR update_printer_sec(struct policy_handle *handle,
6039                                  struct pipes_struct *p,
6040                                  struct sec_desc_buf *secdesc_ctr)
6041 {
6042         struct spoolss_security_descriptor *new_secdesc = NULL;
6043         struct spoolss_security_descriptor *old_secdesc = NULL;
6044         const char *printer;
6045         WERROR result;
6046         int snum;
6047         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6048         struct dcerpc_binding_handle *b;
6049         TALLOC_CTX *tmp_ctx = NULL;
6050
6051         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6052                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6053                          OUR_HANDLE(handle)));
6054
6055                 result = WERR_BADFID;
6056                 goto done;
6057         }
6058
6059         if (secdesc_ctr == NULL) {
6060                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6061                 result = WERR_INVALID_PARAM;
6062                 goto done;
6063         }
6064         printer = lp_const_servicename(snum);
6065
6066         /* Check the user has permissions to change the security
6067            descriptor.  By experimentation with two NT machines, the user
6068            requires Full Access to the printer to change security
6069            information. */
6070
6071         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6072                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6073                 result = WERR_ACCESS_DENIED;
6074                 goto done;
6075         }
6076
6077         tmp_ctx = talloc_new(p->mem_ctx);
6078         if (!tmp_ctx) {
6079                 return WERR_NOMEM;
6080         }
6081
6082         result = winreg_printer_binding_handle(tmp_ctx,
6083                                                get_session_info_system(),
6084                                                p->msg_ctx,
6085                                                &b);
6086         if (!W_ERROR_IS_OK(result)) {
6087                 goto done;
6088         }
6089
6090         /* NT seems to like setting the security descriptor even though
6091            nothing may have actually changed. */
6092         result = winreg_get_printer_secdesc(tmp_ctx, b,
6093                                             printer,
6094                                             &old_secdesc);
6095         if (!W_ERROR_IS_OK(result)) {
6096                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6097                 result = WERR_BADFID;
6098                 goto done;
6099         }
6100
6101         if (DEBUGLEVEL >= 10) {
6102                 struct security_acl *the_acl;
6103                 int i;
6104
6105                 the_acl = old_secdesc->dacl;
6106                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6107                            printer, the_acl->num_aces));
6108
6109                 for (i = 0; i < the_acl->num_aces; i++) {
6110                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6111                                            &the_acl->aces[i].trustee),
6112                                   the_acl->aces[i].access_mask));
6113                 }
6114
6115                 the_acl = secdesc_ctr->sd->dacl;
6116
6117                 if (the_acl) {
6118                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6119                                    printer, the_acl->num_aces));
6120
6121                         for (i = 0; i < the_acl->num_aces; i++) {
6122                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6123                                                    &the_acl->aces[i].trustee),
6124                                            the_acl->aces[i].access_mask));
6125                         }
6126                 } else {
6127                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6128                 }
6129         }
6130
6131         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6132         if (new_secdesc == NULL) {
6133                 result = WERR_NOMEM;
6134                 goto done;
6135         }
6136
6137         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6138                 result = WERR_OK;
6139                 goto done;
6140         }
6141
6142         result = winreg_set_printer_secdesc(tmp_ctx, b,
6143                                             printer,
6144                                             new_secdesc);
6145
6146 done:
6147         talloc_free(tmp_ctx);
6148         return result;
6149 }
6150
6151 /********************************************************************
6152  Canonicalize printer info from a client
6153  ********************************************************************/
6154
6155 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6156                              struct spoolss_SetPrinterInfo2 *info2,
6157                              int snum)
6158 {
6159         fstring printername;
6160         const char *p;
6161
6162         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6163                 "portname=%s drivername=%s comment=%s location=%s\n",
6164                 info2->servername, info2->printername, info2->sharename,
6165                 info2->portname, info2->drivername, info2->comment,
6166                 info2->location));
6167
6168         /* we force some elements to "correct" values */
6169         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6170         if (info2->servername == NULL) {
6171                 return false;
6172         }
6173         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6174         if (info2->sharename == NULL) {
6175                 return false;
6176         }
6177
6178         /* check to see if we allow printername != sharename */
6179         if (lp_force_printername(snum)) {
6180                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6181                                         lp_netbios_name(), info2->sharename);
6182         } else {
6183                 /* make sure printername is in \\server\printername format */
6184                 fstrcpy(printername, info2->printername);
6185                 p = printername;
6186                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6187                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6188                                 p++;
6189                 }
6190
6191                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6192                                         lp_netbios_name(), p);
6193         }
6194         if (info2->printername == NULL) {
6195                 return false;
6196         }
6197
6198         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6199         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6200
6201         return true;
6202 }
6203
6204 /****************************************************************************
6205 ****************************************************************************/
6206
6207 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6208 {
6209         char *cmd = lp_addport_command(talloc_tos());
6210         char *command = NULL;
6211         int ret;
6212         bool is_print_op = false;
6213
6214         if ( !*cmd ) {
6215                 return WERR_ACCESS_DENIED;
6216         }
6217
6218         command = talloc_asprintf(ctx,
6219                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6220         if (!command) {
6221                 return WERR_NOMEM;
6222         }
6223
6224         if ( token )
6225                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6226
6227         DEBUG(10,("Running [%s]\n", command));
6228
6229         /********* BEGIN SePrintOperatorPrivilege **********/
6230
6231         if ( is_print_op )
6232                 become_root();
6233
6234         ret = smbrun(command, NULL);
6235
6236         if ( is_print_op )
6237                 unbecome_root();
6238
6239         /********* END SePrintOperatorPrivilege **********/
6240
6241         DEBUGADD(10,("returned [%d]\n", ret));
6242
6243         TALLOC_FREE(command);
6244
6245         if ( ret != 0 ) {
6246                 return WERR_ACCESS_DENIED;
6247         }
6248
6249         return WERR_OK;
6250 }
6251
6252 /****************************************************************************
6253 ****************************************************************************/
6254
6255 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6256                                    int snum)
6257 {
6258         /*
6259          * As we do not know if we are embedded in the file server process
6260          * or not, we have to pretend that all shares are in use.
6261          */
6262         return true;
6263 }
6264
6265 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6266                              struct spoolss_SetPrinterInfo2 *info2,
6267                              const char *remote_machine,
6268                              struct messaging_context *msg_ctx)
6269 {
6270         char *cmd = lp_addprinter_command(talloc_tos());
6271         char **qlines;
6272         char *command = NULL;
6273         int numlines;
6274         int ret;
6275         int fd;
6276         bool is_print_op = false;
6277
6278         if (!remote_machine) {
6279                 return false;
6280         }
6281
6282         command = talloc_asprintf(ctx,
6283                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6284                         cmd, info2->printername, info2->sharename,
6285                         info2->portname, info2->drivername,
6286                         info2->location, info2->comment, remote_machine);
6287         if (!command) {
6288                 return false;
6289         }
6290
6291         if ( token )
6292                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6293
6294         DEBUG(10,("Running [%s]\n", command));
6295
6296         /********* BEGIN SePrintOperatorPrivilege **********/
6297
6298         if ( is_print_op )
6299                 become_root();
6300
6301         if ( (ret = smbrun(command, &fd)) == 0 ) {
6302                 /* Tell everyone we updated smb.conf. */
6303                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6304         }
6305
6306         if ( is_print_op )
6307                 unbecome_root();
6308
6309         /********* END SePrintOperatorPrivilege **********/
6310
6311         DEBUGADD(10,("returned [%d]\n", ret));
6312
6313         TALLOC_FREE(command);
6314
6315         if ( ret != 0 ) {
6316                 if (fd != -1)
6317                         close(fd);
6318                 return false;
6319         }
6320
6321         /* reload our services immediately */
6322         become_root();
6323         reload_services(NULL, spoolss_conn_snum_used, false);
6324         unbecome_root();
6325
6326         numlines = 0;
6327         /* Get lines and convert them back to dos-codepage */
6328         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6329         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6330         close(fd);
6331
6332         /* Set the portname to what the script says the portname should be. */
6333         /* but don't require anything to be return from the script exit a good error code */
6334
6335         if (numlines) {
6336                 /* Set the portname to what the script says the portname should be. */
6337                 info2->portname = talloc_strdup(ctx, qlines[0]);
6338                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6339         }
6340
6341         TALLOC_FREE(qlines);
6342         return true;
6343 }
6344
6345 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6346                                const struct auth_session_info *session_info,
6347                                struct messaging_context *msg_ctx,
6348                                int snum,
6349                                struct spoolss_SetPrinterInfo2 *printer,
6350                                struct spoolss_PrinterInfo2 *old_printer)
6351 {
6352         bool force_update = (old_printer == NULL);
6353         const char *dnsdomname;
6354         const char *longname;
6355         const char *uncname;
6356         const char *spooling;
6357         DATA_BLOB buffer;
6358         WERROR result = WERR_OK;
6359         struct dcerpc_binding_handle *b;
6360         TALLOC_CTX *tmp_ctx;
6361         bool ok;
6362
6363         tmp_ctx = talloc_new(mem_ctx);
6364         if (!tmp_ctx) {
6365                 return WERR_NOMEM;
6366         }
6367
6368         result = winreg_printer_binding_handle(tmp_ctx,
6369                                                session_info,
6370                                                msg_ctx,
6371                                                &b);
6372         if (!W_ERROR_IS_OK(result)) {
6373                 goto done;
6374         }
6375
6376         if (printer->drivername != NULL &&
6377             (force_update ||
6378              !strequal(printer->drivername, old_printer->drivername))) {
6379                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6380                 if (!ok) {
6381                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6382                         result = WERR_INVALID_DATA;
6383                         goto done;
6384                 }
6385                 result = winreg_set_printer_dataex(tmp_ctx, b,
6386                                           printer->sharename,
6387                                           SPOOL_DSSPOOLER_KEY,
6388                                           SPOOL_REG_DRIVERNAME,
6389                                           REG_SZ,
6390                                           buffer.data,
6391                                           buffer.length);
6392                 if (!W_ERROR_IS_OK(result)) {
6393                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6394                         goto done;
6395                 }
6396
6397                 if (!force_update) {
6398                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6399                                 printer->drivername));
6400
6401                         notify_printer_driver(server_event_context(), msg_ctx,
6402                                               snum, printer->drivername ?
6403                                               printer->drivername : "");
6404                 }
6405         }
6406
6407         if (printer->comment != NULL &&
6408             (force_update ||
6409              !strequal(printer->comment, old_printer->comment))) {
6410                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6411                 if (!ok) {
6412                         DEBUG(0, ("comment data corrupted\n"));
6413                         result = WERR_INVALID_DATA;
6414                         goto done;
6415                 }
6416                 result = winreg_set_printer_dataex(tmp_ctx, b,
6417                                           printer->sharename,
6418                                           SPOOL_DSSPOOLER_KEY,
6419                                           SPOOL_REG_DESCRIPTION,
6420                                           REG_SZ,
6421                                           buffer.data,
6422                                           buffer.length);
6423                 if (!W_ERROR_IS_OK(result)) {
6424                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6425                         goto done;
6426                 }
6427
6428                 if (!force_update) {
6429                         notify_printer_comment(server_event_context(), msg_ctx,
6430                                                snum, printer->comment ?
6431                                                printer->comment : "");
6432                 }
6433         }
6434
6435         if (printer->sharename != NULL &&
6436             (force_update ||
6437              !strequal(printer->sharename, old_printer->sharename))) {
6438                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6439                 if (!ok) {
6440                         DEBUG(0, ("sharename data corrupted\n"));
6441                         result = WERR_INVALID_DATA;
6442                         goto done;
6443                 }
6444                 result = winreg_set_printer_dataex(tmp_ctx, b,
6445                                           printer->sharename,
6446                                           SPOOL_DSSPOOLER_KEY,
6447                                           SPOOL_REG_PRINTSHARENAME,
6448                                           REG_SZ,
6449                                           buffer.data,
6450                                           buffer.length);
6451                 if (!W_ERROR_IS_OK(result)) {
6452                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6453                         goto done;
6454                 }
6455
6456                 if (!force_update) {
6457                         notify_printer_sharename(server_event_context(),
6458                                                  msg_ctx,
6459                                                  snum, printer->sharename ?
6460                                                  printer->sharename : "");
6461                 }
6462         }
6463
6464         if (printer->printername != NULL &&
6465             (force_update ||
6466              !strequal(printer->printername, old_printer->printername))) {
6467                 const char *p;
6468
6469                 p = strrchr(printer->printername, '\\' );
6470                 if (p != NULL) {
6471                         p++;
6472                 } else {
6473                         p = printer->printername;
6474                 }
6475
6476                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6477                 if (!ok) {
6478                         DEBUG(0, ("printername data corrupted\n"));
6479                         result = WERR_INVALID_DATA;
6480                         goto done;
6481                 }
6482                 result = winreg_set_printer_dataex(tmp_ctx, b,
6483                                           printer->sharename,
6484                                           SPOOL_DSSPOOLER_KEY,
6485                                           SPOOL_REG_PRINTERNAME,
6486                                           REG_SZ,
6487                                           buffer.data,
6488                                           buffer.length);
6489                 if (!W_ERROR_IS_OK(result)) {
6490                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6491                         goto done;
6492                 }
6493
6494                 if (!force_update) {
6495                         notify_printer_printername(server_event_context(),
6496                                                    msg_ctx, snum, p ? p : "");
6497                 }
6498         }
6499
6500         if (printer->portname != NULL &&
6501             (force_update ||
6502              !strequal(printer->portname, old_printer->portname))) {
6503                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6504                 if (!ok) {
6505                         DEBUG(0, ("portname data corrupted\n"));
6506                         result = WERR_INVALID_DATA;
6507                         goto done;
6508                 }
6509                 result = winreg_set_printer_dataex(tmp_ctx, b,
6510                                           printer->sharename,
6511                                           SPOOL_DSSPOOLER_KEY,
6512                                           SPOOL_REG_PORTNAME,
6513                                           REG_SZ,
6514                                           buffer.data,
6515                                           buffer.length);
6516                 if (!W_ERROR_IS_OK(result)) {
6517                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6518                         goto done;
6519                 }
6520
6521                 if (!force_update) {
6522                         notify_printer_port(server_event_context(),
6523                                             msg_ctx, snum, printer->portname ?
6524                                             printer->portname : "");
6525                 }
6526         }
6527
6528         if (printer->location != NULL &&
6529             (force_update ||
6530              !strequal(printer->location, old_printer->location))) {
6531                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6532                 if (!ok) {
6533                         DEBUG(0, ("location data corrupted\n"));
6534                         result = WERR_INVALID_DATA;
6535                         goto done;
6536                 }
6537                 result = winreg_set_printer_dataex(tmp_ctx, b,
6538                                           printer->sharename,
6539                                           SPOOL_DSSPOOLER_KEY,
6540                                           SPOOL_REG_LOCATION,
6541                                           REG_SZ,
6542                                           buffer.data,
6543                                           buffer.length);
6544                 if (!W_ERROR_IS_OK(result)) {
6545                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6546                         goto done;
6547                 }
6548
6549                 if (!force_update) {
6550                         notify_printer_location(server_event_context(),
6551                                                 msg_ctx, snum,
6552                                                 printer->location ?
6553                                                 printer->location : "");
6554                 }
6555         }
6556
6557         if (printer->sepfile != NULL &&
6558             (force_update ||
6559              !strequal(printer->sepfile, old_printer->sepfile))) {
6560                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6561                 if (!ok) {
6562                         DEBUG(0, ("sepfile data corrupted\n"));
6563                         result = WERR_INVALID_DATA;
6564                         goto done;
6565                 }
6566                 result = winreg_set_printer_dataex(tmp_ctx, b,
6567                                           printer->sharename,
6568                                           SPOOL_DSSPOOLER_KEY,
6569                                           SPOOL_REG_PRINTSEPARATORFILE,
6570                                           REG_SZ,
6571                                           buffer.data,
6572                                           buffer.length);
6573                 if (!W_ERROR_IS_OK(result)) {
6574                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6575                         goto done;
6576                 }
6577
6578                 if (!force_update) {
6579                         notify_printer_sepfile(server_event_context(),
6580                                                msg_ctx, snum,
6581                                                printer->sepfile ?
6582                                                printer->sepfile : "");
6583                 }
6584         }
6585
6586         if (printer->starttime != 0 &&
6587             (force_update ||
6588              printer->starttime != old_printer->starttime)) {
6589                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6590                 SIVAL(buffer.data, 0, printer->starttime);
6591                 result = winreg_set_printer_dataex(tmp_ctx, b,
6592                                           printer->sharename,
6593                                           SPOOL_DSSPOOLER_KEY,
6594                                           SPOOL_REG_PRINTSTARTTIME,
6595                                           REG_DWORD,
6596                                           buffer.data,
6597                                           buffer.length);
6598                 if (!W_ERROR_IS_OK(result)) {
6599                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6600                         goto done;
6601                 }
6602         }
6603
6604         if (printer->untiltime != 0 &&
6605             (force_update ||
6606              printer->untiltime != old_printer->untiltime)) {
6607                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6608                 SIVAL(buffer.data, 0, printer->untiltime);
6609                 result = winreg_set_printer_dataex(tmp_ctx, b,
6610                                           printer->sharename,
6611                                           SPOOL_DSSPOOLER_KEY,
6612                                           SPOOL_REG_PRINTENDTIME,
6613                                           REG_DWORD,
6614                                           buffer.data,
6615                                           buffer.length);
6616                 if (!W_ERROR_IS_OK(result)) {
6617                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6618                         goto done;
6619                 }
6620         }
6621
6622         if (force_update || printer->priority != old_printer->priority) {
6623                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6624                 SIVAL(buffer.data, 0, printer->priority);
6625                 result = winreg_set_printer_dataex(tmp_ctx, b,
6626                                           printer->sharename,
6627                                           SPOOL_DSSPOOLER_KEY,
6628                                           SPOOL_REG_PRIORITY,
6629                                           REG_DWORD,
6630                                           buffer.data,
6631                                           buffer.length);
6632                 if (!W_ERROR_IS_OK(result)) {
6633                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6634                         goto done;
6635                 }
6636         }
6637
6638         if (force_update || printer->attributes != old_printer->attributes) {
6639                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6640                 SIVAL(buffer.data, 0, (printer->attributes &
6641                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6642                 result = winreg_set_printer_dataex(tmp_ctx, b,
6643                                           printer->sharename,
6644                                           SPOOL_DSSPOOLER_KEY,
6645                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6646                                           REG_DWORD,
6647                                           buffer.data,
6648                                           buffer.length);
6649                 if (!W_ERROR_IS_OK(result)) {
6650                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6651                         goto done;
6652                 }
6653
6654                 switch (printer->attributes & 0x3) {
6655                         case 0:
6656                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6657                                 break;
6658                         case 1:
6659                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6660                                 break;
6661                         case 2:
6662                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6663                                 break;
6664                         default:
6665                                 spooling = "unknown";
6666                 }
6667                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6668                 if (!ok) {
6669                         DEBUG(0, ("printSpooling data corrupted\n"));
6670                         result = WERR_INVALID_DATA;
6671                         goto done;
6672                 }
6673                 winreg_set_printer_dataex(tmp_ctx, b,
6674                                           printer->sharename,
6675                                           SPOOL_DSSPOOLER_KEY,
6676                                           SPOOL_REG_PRINTSPOOLING,
6677                                           REG_SZ,
6678                                           buffer.data,
6679                                           buffer.length);
6680         }
6681
6682         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6683         if (!ok) {
6684                 DEBUG(0, ("shortServerName data corrupted\n"));
6685                 result = WERR_INVALID_DATA;
6686                 goto done;
6687         }
6688         result = winreg_set_printer_dataex(tmp_ctx, b,
6689                                   printer->sharename,
6690                                   SPOOL_DSSPOOLER_KEY,
6691                                   SPOOL_REG_SHORTSERVERNAME,
6692                                   REG_SZ,
6693                                   buffer.data,
6694                                   buffer.length);
6695         if (!W_ERROR_IS_OK(result)) {
6696                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6697                 goto done;
6698         }
6699
6700         dnsdomname = get_mydnsfullname();
6701         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6702                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6703         } else {
6704                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6705         }
6706         if (longname == NULL) {
6707                 result = WERR_NOMEM;
6708                 goto done;
6709         }
6710
6711         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6712         if (!ok) {
6713                 DEBUG(0, ("longname data corrupted\n"));
6714                 result = WERR_INVALID_DATA;
6715                 goto done;
6716         }
6717         result = winreg_set_printer_dataex(tmp_ctx, b,
6718                                            printer->sharename,
6719                                            SPOOL_DSSPOOLER_KEY,
6720                                            SPOOL_REG_SERVERNAME,
6721                                            REG_SZ,
6722                                            buffer.data,
6723                                            buffer.length);
6724         if (!W_ERROR_IS_OK(result)) {
6725                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6726                 goto done;
6727         }
6728
6729         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6730                                   lp_netbios_name(), printer->sharename);
6731         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6732         if (!ok) {
6733                 DEBUG(0, ("uncName data corrupted\n"));
6734                 result = WERR_INVALID_DATA;
6735                 goto done;
6736         }
6737         result = winreg_set_printer_dataex(tmp_ctx, b,
6738                                   printer->sharename,
6739                                   SPOOL_DSSPOOLER_KEY,
6740                                   SPOOL_REG_UNCNAME,
6741                                   REG_SZ,
6742                                   buffer.data,
6743                                   buffer.length);
6744         if (!W_ERROR_IS_OK(result)) {
6745                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6746                 goto done;
6747         }
6748
6749 done:
6750         talloc_free(tmp_ctx);
6751         return result;
6752 }
6753
6754 /********************************************************************
6755  * Called by spoolss_api_setprinter
6756  * when updating a printer description.
6757  ********************************************************************/
6758
6759 static WERROR update_printer(struct pipes_struct *p,
6760                              struct policy_handle *handle,
6761                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6762                              struct spoolss_DeviceMode *devmode)
6763 {
6764         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6765         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6766         struct spoolss_PrinterInfo2 *old_printer;
6767         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6768         int snum;
6769         WERROR result = WERR_OK;
6770         TALLOC_CTX *tmp_ctx;
6771         struct dcerpc_binding_handle *b;
6772
6773         DEBUG(8,("update_printer\n"));
6774
6775         tmp_ctx = talloc_new(p->mem_ctx);
6776         if (tmp_ctx == NULL) {
6777                 return WERR_NOMEM;
6778         }
6779
6780         if (!Printer) {
6781                 result = WERR_BADFID;
6782                 goto done;
6783         }
6784
6785         if (!get_printer_snum(p, handle, &snum, NULL)) {
6786                 result = WERR_BADFID;
6787                 goto done;
6788         }
6789
6790         result = winreg_printer_binding_handle(tmp_ctx,
6791                                                get_session_info_system(),
6792                                                p->msg_ctx,
6793                                                &b);
6794         if (!W_ERROR_IS_OK(result)) {
6795                 goto done;
6796         }
6797
6798         result = winreg_get_printer(tmp_ctx, b,
6799                                     lp_const_servicename(snum),
6800                                     &old_printer);
6801         if (!W_ERROR_IS_OK(result)) {
6802                 result = WERR_BADFID;
6803                 goto done;
6804         }
6805
6806         /* Do sanity check on the requested changes for Samba */
6807         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6808                 result = WERR_INVALID_PARAM;
6809                 goto done;
6810         }
6811
6812         /* FIXME!!! If the driver has changed we really should verify that
6813            it is installed before doing much else   --jerry */
6814
6815         /* Check calling user has permission to update printer description */
6816         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6817                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6818                 result = WERR_ACCESS_DENIED;
6819                 goto done;
6820         }
6821
6822         /* Call addprinter hook */
6823         /* Check changes to see if this is really needed */
6824
6825         if (*lp_addprinter_command(talloc_tos()) &&
6826                         (!strequal(printer->drivername, old_printer->drivername) ||
6827                          !strequal(printer->comment, old_printer->comment) ||
6828                          !strequal(printer->portname, old_printer->portname) ||
6829                          !strequal(printer->location, old_printer->location)) )
6830         {
6831                 char *raddr;
6832
6833                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6834                                                          p->mem_ctx);
6835                 if (raddr == NULL) {
6836                         return WERR_NOMEM;
6837                 }
6838
6839                 /* add_printer_hook() will call reload_services() */
6840                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6841                                       printer, raddr,
6842                                       p->msg_ctx)) {
6843                         result = WERR_ACCESS_DENIED;
6844                         goto done;
6845                 }
6846         }
6847
6848         result = update_dsspooler(tmp_ctx,
6849                                   get_session_info_system(),
6850                                   p->msg_ctx,
6851                                   snum,
6852                                   printer,
6853                                   old_printer);
6854         if (!W_ERROR_IS_OK(result)) {
6855                 goto done;
6856         }
6857
6858         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6859
6860         if (devmode == NULL) {
6861                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6862         }
6863         result = winreg_update_printer(tmp_ctx, b,
6864                                        printer->sharename,
6865                                        printer_mask,
6866                                        printer,
6867                                        devmode,
6868                                        NULL);
6869
6870 done:
6871         talloc_free(tmp_ctx);
6872
6873         return result;
6874 }
6875
6876 /****************************************************************************
6877 ****************************************************************************/
6878 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6879                                            struct policy_handle *handle,
6880                                            struct spoolss_SetPrinterInfo7 *info7)
6881 {
6882 #ifdef HAVE_ADS
6883         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6884         WERROR result;
6885         int snum;
6886         struct printer_handle *Printer;
6887
6888         if ( lp_security() != SEC_ADS ) {
6889                 return WERR_UNKNOWN_LEVEL;
6890         }
6891
6892         Printer = find_printer_index_by_hnd(p, handle);
6893
6894         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6895
6896         if (!Printer)
6897                 return WERR_BADFID;
6898
6899         if (!get_printer_snum(p, handle, &snum, NULL))
6900                 return WERR_BADFID;
6901
6902         result = winreg_get_printer_internal(p->mem_ctx,
6903                                     get_session_info_system(),
6904                                     p->msg_ctx,
6905                                     lp_servicename(talloc_tos(), snum),
6906                                     &pinfo2);
6907         if (!W_ERROR_IS_OK(result)) {
6908                 return WERR_BADFID;
6909         }
6910
6911         nt_printer_publish(pinfo2,
6912                            get_session_info_system(),
6913                            p->msg_ctx,
6914                            pinfo2,
6915                            info7->action);
6916
6917         TALLOC_FREE(pinfo2);
6918         return WERR_OK;
6919 #else
6920         return WERR_UNKNOWN_LEVEL;
6921 #endif
6922 }
6923
6924 /********************************************************************
6925  ********************************************************************/
6926
6927 static WERROR update_printer_devmode(struct pipes_struct *p,
6928                                      struct policy_handle *handle,
6929                                      struct spoolss_DeviceMode *devmode)
6930 {
6931         int snum;
6932         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6933         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6934
6935         DEBUG(8,("update_printer_devmode\n"));
6936
6937         if (!Printer) {
6938                 return WERR_BADFID;
6939         }
6940
6941         if (!get_printer_snum(p, handle, &snum, NULL)) {
6942                 return WERR_BADFID;
6943         }
6944
6945         /* Check calling user has permission to update printer description */
6946         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6947                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6948                 return WERR_ACCESS_DENIED;
6949         }
6950
6951         return winreg_update_printer_internal(p->mem_ctx,
6952                                      get_session_info_system(),
6953                                      p->msg_ctx,
6954                                      lp_const_servicename(snum),
6955                                      info2_mask,
6956                                      NULL,
6957                                      devmode,
6958                                      NULL);
6959 }
6960
6961
6962 /****************************************************************
6963  _spoolss_SetPrinter
6964 ****************************************************************/
6965
6966 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6967                            struct spoolss_SetPrinter *r)
6968 {
6969         WERROR result;
6970
6971         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6972
6973         if (!Printer) {
6974                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6975                         OUR_HANDLE(r->in.handle)));
6976                 return WERR_BADFID;
6977         }
6978
6979         /* check the level */
6980         switch (r->in.info_ctr->level) {
6981                 case 0:
6982                         return control_printer(r->in.handle, r->in.command, p);
6983                 case 2:
6984                         result = update_printer(p, r->in.handle,
6985                                                 r->in.info_ctr,
6986                                                 r->in.devmode_ctr->devmode);
6987                         if (!W_ERROR_IS_OK(result))
6988                                 return result;
6989                         if (r->in.secdesc_ctr->sd)
6990                                 result = update_printer_sec(r->in.handle, p,
6991                                                             r->in.secdesc_ctr);
6992                         return result;
6993                 case 3:
6994                         return update_printer_sec(r->in.handle, p,
6995                                                   r->in.secdesc_ctr);
6996                 case 7:
6997                         return publish_or_unpublish_printer(p, r->in.handle,
6998                                                             r->in.info_ctr->info.info7);
6999                 case 8:
7000                         return update_printer_devmode(p, r->in.handle,
7001                                                       r->in.devmode_ctr->devmode);
7002                 default:
7003                         return WERR_UNKNOWN_LEVEL;
7004         }
7005 }
7006
7007 /****************************************************************
7008  _spoolss_FindClosePrinterNotify
7009 ****************************************************************/
7010
7011 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7012                                        struct spoolss_FindClosePrinterNotify *r)
7013 {
7014         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7015
7016         if (!Printer) {
7017                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7018                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7019                 return WERR_BADFID;
7020         }
7021
7022         if (Printer->notify.cli_chan != NULL &&
7023             Printer->notify.cli_chan->active_connections > 0) {
7024                 int snum = -1;
7025
7026                 if (Printer->printer_type == SPLHND_PRINTER) {
7027                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7028                                 return WERR_BADFID;
7029                         }
7030                 }
7031
7032                 srv_spoolss_replycloseprinter(snum, Printer);
7033         }
7034
7035         Printer->notify.flags=0;
7036         Printer->notify.options=0;
7037         Printer->notify.localmachine[0]='\0';
7038         Printer->notify.printerlocal=0;
7039         TALLOC_FREE(Printer->notify.option);
7040
7041         return WERR_OK;
7042 }
7043
7044 /****************************************************************
7045  _spoolss_AddJob
7046 ****************************************************************/
7047
7048 WERROR _spoolss_AddJob(struct pipes_struct *p,
7049                        struct spoolss_AddJob *r)
7050 {
7051         if (!r->in.buffer && (r->in.offered != 0)) {
7052                 return WERR_INVALID_PARAM;
7053         }
7054
7055         /* this is what a NT server returns for AddJob. AddJob must fail on
7056          * non-local printers */
7057
7058         if (r->in.level != 1) {
7059                 return WERR_UNKNOWN_LEVEL;
7060         }
7061
7062         return WERR_INVALID_PARAM;
7063 }
7064
7065 /****************************************************************************
7066 fill_job_info1
7067 ****************************************************************************/
7068
7069 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7070                              struct spoolss_JobInfo1 *r,
7071                              const print_queue_struct *queue,
7072                              uint32_t jobid,
7073                              int position, int snum,
7074                              struct spoolss_PrinterInfo2 *pinfo2)
7075 {
7076         struct tm *t;
7077
7078         t = gmtime(&queue->time);
7079
7080         r->job_id               = jobid;
7081
7082         r->printer_name         = lp_servicename(mem_ctx, snum);
7083         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7084         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7085         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7086         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7087         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7088         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7089         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7090         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7091         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7092         r->text_status          = talloc_strdup(mem_ctx, "");
7093         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7094
7095         r->status               = nt_printj_status(queue->status);
7096         r->priority             = queue->priority;
7097         r->position             = position;
7098         r->total_pages          = queue->page_count;
7099         r->pages_printed        = 0; /* ??? */
7100
7101         init_systemtime(&r->submitted, t);
7102
7103         return WERR_OK;
7104 }
7105
7106 /****************************************************************************
7107 fill_job_info2
7108 ****************************************************************************/
7109
7110 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7111                              struct spoolss_JobInfo2 *r,
7112                              const print_queue_struct *queue,
7113                              uint32_t jobid,
7114                              int position, int snum,
7115                              struct spoolss_PrinterInfo2 *pinfo2,
7116                              struct spoolss_DeviceMode *devmode)
7117 {
7118         struct tm *t;
7119
7120         t = gmtime(&queue->time);
7121
7122         r->job_id               = jobid;
7123
7124         r->printer_name         = lp_servicename(mem_ctx, snum);
7125         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7126         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7127         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7128         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7129         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7130         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7131         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7132         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7133         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7134         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7135         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7136         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7137         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7138         r->parameters           = talloc_strdup(mem_ctx, "");
7139         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7140         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7141         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7142
7143         r->devmode              = devmode;
7144
7145         r->text_status          = talloc_strdup(mem_ctx, "");
7146         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7147
7148         r->secdesc              = NULL;
7149
7150         r->status               = nt_printj_status(queue->status);
7151         r->priority             = queue->priority;
7152         r->position             = position;
7153         r->start_time           = 0;
7154         r->until_time           = 0;
7155         r->total_pages          = queue->page_count;
7156         r->size                 = queue->size;
7157         init_systemtime(&r->submitted, t);
7158         r->time                 = 0;
7159         r->pages_printed        = 0; /* ??? */
7160
7161         return WERR_OK;
7162 }
7163
7164 /****************************************************************************
7165  Enumjobs at level 1.
7166 ****************************************************************************/
7167
7168 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7169                               const print_queue_struct *queue,
7170                               uint32_t num_queues, int snum,
7171                               struct spoolss_PrinterInfo2 *pinfo2,
7172                               union spoolss_JobInfo **info_p,
7173                               uint32_t *count)
7174 {
7175         union spoolss_JobInfo *info;
7176         int i;
7177         WERROR result = WERR_OK;
7178         uint32_t num_filled;
7179         struct tdb_print_db *pdb;
7180
7181         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7182         if (info == NULL) {
7183                 result = WERR_NOMEM;
7184                 goto err_out;
7185         }
7186
7187         pdb = get_print_db_byname(pinfo2->sharename);
7188         if (pdb == NULL) {
7189                 result = WERR_INVALID_PARAM;
7190                 goto err_info_free;
7191         }
7192
7193         num_filled = 0;
7194         for (i = 0; i < num_queues; i++) {
7195                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7196                 if (jobid == (uint32_t)-1) {
7197                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7198                         continue;
7199                 }
7200
7201                 result = fill_job_info1(info,
7202                                         &info[num_filled].info1,
7203                                         &queue[i],
7204                                         jobid,
7205                                         i,
7206                                         snum,
7207                                         pinfo2);
7208                 if (!W_ERROR_IS_OK(result)) {
7209                         goto err_pdb_drop;
7210                 }
7211
7212                 num_filled++;
7213         }
7214
7215         release_print_db(pdb);
7216         *info_p = info;
7217         *count = num_filled;
7218
7219         return WERR_OK;
7220
7221 err_pdb_drop:
7222         release_print_db(pdb);
7223 err_info_free:
7224         TALLOC_FREE(info);
7225 err_out:
7226         *count = 0;
7227         return result;
7228 }
7229
7230 /****************************************************************************
7231  Enumjobs at level 2.
7232 ****************************************************************************/
7233
7234 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7235                               const print_queue_struct *queue,
7236                               uint32_t num_queues, int snum,
7237                               struct spoolss_PrinterInfo2 *pinfo2,
7238                               union spoolss_JobInfo **info_p,
7239                               uint32_t *count)
7240 {
7241         union spoolss_JobInfo *info;
7242         int i;
7243         WERROR result = WERR_OK;
7244         uint32_t num_filled;
7245         struct tdb_print_db *pdb;
7246
7247         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7248         if (info == NULL) {
7249                 result = WERR_NOMEM;
7250                 goto err_out;
7251         }
7252
7253         pdb = get_print_db_byname(pinfo2->sharename);
7254         if (pdb == NULL) {
7255                 result = WERR_INVALID_PARAM;
7256                 goto err_info_free;
7257         }
7258
7259         num_filled = 0;
7260         for (i = 0; i< num_queues; i++) {
7261                 struct spoolss_DeviceMode *devmode;
7262                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7263                 if (jobid == (uint32_t)-1) {
7264                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7265                         continue;
7266                 }
7267
7268                 result = spoolss_create_default_devmode(info,
7269                                                         pinfo2->printername,
7270                                                         &devmode);
7271                 if (!W_ERROR_IS_OK(result)) {
7272                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7273                         goto err_pdb_drop;
7274                 }
7275
7276                 result = fill_job_info2(info,
7277                                         &info[num_filled].info2,
7278                                         &queue[i],
7279                                         jobid,
7280                                         i,
7281                                         snum,
7282                                         pinfo2,
7283                                         devmode);
7284                 if (!W_ERROR_IS_OK(result)) {
7285                         goto err_pdb_drop;
7286                 }
7287                 num_filled++;
7288         }
7289
7290         release_print_db(pdb);
7291         *info_p = info;
7292         *count = num_filled;
7293
7294         return WERR_OK;
7295
7296 err_pdb_drop:
7297         release_print_db(pdb);
7298 err_info_free:
7299         TALLOC_FREE(info);
7300 err_out:
7301         *count = 0;
7302         return result;
7303 }
7304
7305 /****************************************************************************
7306  Enumjobs at level 3.
7307 ****************************************************************************/
7308
7309 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7310                               const print_queue_struct *queue,
7311                               uint32_t num_queues, int snum,
7312                               struct spoolss_PrinterInfo2 *pinfo2,
7313                               union spoolss_JobInfo **info_p,
7314                               uint32_t *count)
7315 {
7316         union spoolss_JobInfo *info;
7317         int i;
7318         WERROR result = WERR_OK;
7319         uint32_t num_filled;
7320         struct tdb_print_db *pdb;
7321
7322         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7323         if (info == NULL) {
7324                 result = WERR_NOMEM;
7325                 goto err_out;
7326         }
7327
7328         pdb = get_print_db_byname(pinfo2->sharename);
7329         if (pdb == NULL) {
7330                 result = WERR_INVALID_PARAM;
7331                 goto err_info_free;
7332         }
7333
7334         num_filled = 0;
7335         for (i = 0; i < num_queues; i++) {
7336                 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7337                 if (jobid == (uint32_t)-1) {
7338                         DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7339                         continue;
7340                 }
7341
7342                 info[num_filled].info3.job_id = jobid;
7343                 /* next_job_id is overwritten on next iteration */
7344                 info[num_filled].info3.next_job_id = 0;
7345                 info[num_filled].info3.reserved = 0;
7346
7347                 if (num_filled > 0) {
7348                         info[num_filled - 1].info3.next_job_id = jobid;
7349                 }
7350                 num_filled++;
7351         }
7352
7353         release_print_db(pdb);
7354         *info_p = info;
7355         *count = num_filled;
7356
7357         return WERR_OK;
7358
7359 err_info_free:
7360         TALLOC_FREE(info);
7361 err_out:
7362         *count = 0;
7363         return result;
7364 }
7365
7366 /****************************************************************
7367  _spoolss_EnumJobs
7368 ****************************************************************/
7369
7370 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7371                          struct spoolss_EnumJobs *r)
7372 {
7373         WERROR result;
7374         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7375         int snum;
7376         print_status_struct prt_status;
7377         print_queue_struct *queue = NULL;
7378         uint32_t count;
7379
7380         /* that's an [in out] buffer */
7381
7382         if (!r->in.buffer && (r->in.offered != 0)) {
7383                 return WERR_INVALID_PARAM;
7384         }
7385
7386         if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7387                 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7388                 return WERR_UNKNOWN_LEVEL;
7389         }
7390
7391         DEBUG(4,("_spoolss_EnumJobs\n"));
7392
7393         *r->out.needed = 0;
7394         *r->out.count = 0;
7395         *r->out.info = NULL;
7396
7397         /* lookup the printer snum and tdb entry */
7398
7399         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7400                 return WERR_BADFID;
7401         }
7402
7403         result = winreg_get_printer_internal(p->mem_ctx,
7404                                     get_session_info_system(),
7405                                     p->msg_ctx,
7406                                     lp_const_servicename(snum),
7407                                     &pinfo2);
7408         if (!W_ERROR_IS_OK(result)) {
7409                 return result;
7410         }
7411
7412         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7413         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7414                 count, prt_status.status, prt_status.message));
7415
7416         if (count == 0) {
7417                 SAFE_FREE(queue);
7418                 TALLOC_FREE(pinfo2);
7419                 return WERR_OK;
7420         }
7421
7422         switch (r->in.level) {
7423         case 1:
7424                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7425                                          pinfo2, r->out.info, r->out.count);
7426                 break;
7427         case 2:
7428                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7429                                          pinfo2, r->out.info, r->out.count);
7430                 break;
7431         case 3:
7432                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7433                                          pinfo2, r->out.info, r->out.count);
7434                 break;
7435         default:
7436                 SMB_ASSERT(false);      /* level checked on entry */
7437                 break;
7438         }
7439
7440         SAFE_FREE(queue);
7441         TALLOC_FREE(pinfo2);
7442
7443         if (!W_ERROR_IS_OK(result)) {
7444                 return result;
7445         }
7446
7447         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7448                                                      spoolss_EnumJobs,
7449                                                      *r->out.info, r->in.level,
7450                                                      *r->out.count);
7451         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7452         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7453
7454         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7455 }
7456
7457 /****************************************************************
7458  _spoolss_ScheduleJob
7459 ****************************************************************/
7460
7461 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7462                             struct spoolss_ScheduleJob *r)
7463 {
7464         return WERR_OK;
7465 }
7466
7467 /****************************************************************
7468 ****************************************************************/
7469
7470 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7471                                struct messaging_context *msg_ctx,
7472                                const char *printer_name,
7473                                uint32_t job_id,
7474                                struct spoolss_SetJobInfo1 *r)
7475 {
7476         char *old_doc_name;
7477
7478         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7479                 return WERR_BADFID;
7480         }
7481
7482         if (strequal(old_doc_name, r->document_name)) {
7483                 return WERR_OK;
7484         }
7485
7486         if (!print_job_set_name(server_event_context(), msg_ctx,
7487                                 printer_name, job_id, r->document_name)) {
7488                 return WERR_BADFID;
7489         }
7490
7491         return WERR_OK;
7492 }
7493
7494 /****************************************************************
7495  _spoolss_SetJob
7496 ****************************************************************/
7497
7498 WERROR _spoolss_SetJob(struct pipes_struct *p,
7499                        struct spoolss_SetJob *r)
7500 {
7501         const struct auth_session_info *session_info = p->session_info;
7502         int snum;
7503         WERROR errcode = WERR_BADFUNC;
7504
7505         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7506                 return WERR_BADFID;
7507         }
7508
7509         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7510                 return WERR_INVALID_PRINTER_NAME;
7511         }
7512
7513         switch (r->in.command) {
7514         case SPOOLSS_JOB_CONTROL_CANCEL:
7515         case SPOOLSS_JOB_CONTROL_DELETE:
7516                 errcode = print_job_delete(session_info, p->msg_ctx,
7517                                            snum, r->in.job_id);
7518                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7519                         errcode = WERR_OK;
7520                 }
7521                 break;
7522         case SPOOLSS_JOB_CONTROL_PAUSE:
7523                 errcode = print_job_pause(session_info, p->msg_ctx,
7524                                           snum, r->in.job_id);
7525                 break;
7526         case SPOOLSS_JOB_CONTROL_RESTART:
7527         case SPOOLSS_JOB_CONTROL_RESUME:
7528                 errcode = print_job_resume(session_info, p->msg_ctx,
7529                                            snum, r->in.job_id);
7530                 break;
7531         case 0:
7532                 errcode = WERR_OK;
7533                 break;
7534         default:
7535                 return WERR_UNKNOWN_LEVEL;
7536         }
7537
7538         if (!W_ERROR_IS_OK(errcode)) {
7539                 return errcode;
7540         }
7541
7542         if (r->in.ctr == NULL) {
7543                 return errcode;
7544         }
7545
7546         switch (r->in.ctr->level) {
7547         case 1:
7548                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7549                                            lp_const_servicename(snum),
7550                                            r->in.job_id,
7551                                            r->in.ctr->info.info1);
7552                 break;
7553         case 2:
7554         case 3:
7555         case 4:
7556         default:
7557                 return WERR_UNKNOWN_LEVEL;
7558         }
7559
7560         return errcode;
7561 }
7562
7563 /****************************************************************************
7564  Enumerates all printer drivers by level and architecture.
7565 ****************************************************************************/
7566
7567 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7568                                                        const struct auth_session_info *session_info,
7569                                                        struct messaging_context *msg_ctx,
7570                                                        const char *servername,
7571                                                        const char *architecture,
7572                                                        uint32_t level,
7573                                                        union spoolss_DriverInfo **info_p,
7574                                                        uint32_t *count_p)
7575 {
7576         int i;
7577         uint32_t version;
7578         struct spoolss_DriverInfo8 *driver;
7579         union spoolss_DriverInfo *info = NULL;
7580         uint32_t count = 0;
7581         WERROR result = WERR_OK;
7582         uint32_t num_drivers;
7583         const char **drivers;
7584         struct dcerpc_binding_handle *b;
7585         TALLOC_CTX *tmp_ctx = NULL;
7586
7587         *count_p = 0;
7588         *info_p = NULL;
7589
7590         tmp_ctx = talloc_new(mem_ctx);
7591         if (!tmp_ctx) {
7592                 return WERR_NOMEM;
7593         }
7594
7595         result = winreg_printer_binding_handle(tmp_ctx,
7596                                                session_info,
7597                                                msg_ctx,
7598                                                &b);
7599         if (!W_ERROR_IS_OK(result)) {
7600                 goto out;
7601         }
7602
7603         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7604                 result = winreg_get_driver_list(tmp_ctx, b,
7605                                                 architecture, version,
7606                                                 &num_drivers, &drivers);
7607                 if (!W_ERROR_IS_OK(result)) {
7608                         goto out;
7609                 }
7610                 DEBUG(4, ("we have:[%d] drivers in environment"
7611                           " [%s] and version [%d]\n",
7612                           num_drivers, architecture, version));
7613
7614                 if (num_drivers != 0) {
7615                         info = talloc_realloc(tmp_ctx, info,
7616                                                     union spoolss_DriverInfo,
7617                                                     count + num_drivers);
7618                         if (!info) {
7619                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7620                                         "failed to enlarge driver info buffer!\n"));
7621                                 result = WERR_NOMEM;
7622                                 goto out;
7623                         }
7624                 }
7625
7626                 for (i = 0; i < num_drivers; i++) {
7627                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7628
7629                         result = winreg_get_driver(tmp_ctx, b,
7630                                                    architecture, drivers[i],
7631                                                    version, &driver);
7632                         if (!W_ERROR_IS_OK(result)) {
7633                                 goto out;
7634                         }
7635
7636                         switch (level) {
7637                         case 1:
7638                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7639                                                                    driver, servername);
7640                                 break;
7641                         case 2:
7642                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7643                                                                    driver, servername);
7644                                 break;
7645                         case 3:
7646                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7647                                                                    driver, servername);
7648                                 break;
7649                         case 4:
7650                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7651                                                                    driver, servername);
7652                                 break;
7653                         case 5:
7654                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7655                                                                    driver, servername);
7656                                 break;
7657                         case 6:
7658                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7659                                                                    driver, servername);
7660                                 break;
7661                         case 8:
7662                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7663                                                                    driver, servername);
7664                                 break;
7665                         default:
7666                                 result = WERR_UNKNOWN_LEVEL;
7667                                 break;
7668                         }
7669
7670                         TALLOC_FREE(driver);
7671
7672                         if (!W_ERROR_IS_OK(result)) {
7673                                 goto out;
7674                         }
7675                 }
7676
7677                 count += num_drivers;
7678                 TALLOC_FREE(drivers);
7679         }
7680
7681 out:
7682         if (W_ERROR_IS_OK(result)) {
7683                 *info_p = talloc_move(mem_ctx, &info);
7684                 *count_p = count;
7685         }
7686
7687         talloc_free(tmp_ctx);
7688         return result;
7689 }
7690
7691 /****************************************************************************
7692  Enumerates all printer drivers by level.
7693 ****************************************************************************/
7694
7695 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7696                                        const struct auth_session_info *session_info,
7697                                        struct messaging_context *msg_ctx,
7698                                        const char *servername,
7699                                        const char *architecture,
7700                                        uint32_t level,
7701                                        union spoolss_DriverInfo **info_p,
7702                                        uint32_t *count_p)
7703 {
7704         uint32_t a,i;
7705         WERROR result = WERR_OK;
7706
7707         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7708
7709                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7710
7711                         union spoolss_DriverInfo *info = NULL;
7712                         uint32_t count = 0;
7713
7714                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7715                                                                           session_info,
7716                                                                           msg_ctx,
7717                                                                           servername,
7718                                                                           archi_table[a].long_archi,
7719                                                                           level,
7720                                                                           &info,
7721                                                                           &count);
7722                         if (!W_ERROR_IS_OK(result)) {
7723                                 continue;
7724                         }
7725
7726                         for (i=0; i < count; i++) {
7727                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7728                                              info[i], info_p, count_p);
7729                         }
7730                 }
7731
7732                 return result;
7733         }
7734
7735         return enumprinterdrivers_level_by_architecture(mem_ctx,
7736                                                         session_info,
7737                                                         msg_ctx,
7738                                                         servername,
7739                                                         architecture,
7740                                                         level,
7741                                                         info_p,
7742                                                         count_p);
7743 }
7744
7745 /****************************************************************
7746  _spoolss_EnumPrinterDrivers
7747 ****************************************************************/
7748
7749 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7750                                    struct spoolss_EnumPrinterDrivers *r)
7751 {
7752         const char *cservername;
7753         WERROR result;
7754
7755         /* that's an [in out] buffer */
7756
7757         if (!r->in.buffer && (r->in.offered != 0)) {
7758                 return WERR_INVALID_PARAM;
7759         }
7760
7761         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7762
7763         *r->out.needed = 0;
7764         *r->out.count = 0;
7765         *r->out.info = NULL;
7766
7767         cservername = canon_servername(r->in.server);
7768
7769         if (!is_myname_or_ipaddr(cservername)) {
7770                 return WERR_UNKNOWN_PRINTER_DRIVER;
7771         }
7772
7773         result = enumprinterdrivers_level(p->mem_ctx,
7774                                           get_session_info_system(),
7775                                           p->msg_ctx,
7776                                           cservername,
7777                                           r->in.environment,
7778                                           r->in.level,
7779                                           r->out.info,
7780                                           r->out.count);
7781         if (!W_ERROR_IS_OK(result)) {
7782                 return result;
7783         }
7784
7785         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7786                                                      spoolss_EnumPrinterDrivers,
7787                                                      *r->out.info, r->in.level,
7788                                                      *r->out.count);
7789         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7790         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7791
7792         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7793 }
7794
7795 /****************************************************************
7796  _spoolss_EnumForms
7797 ****************************************************************/
7798
7799 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7800                           struct spoolss_EnumForms *r)
7801 {
7802         WERROR result;
7803
7804         *r->out.count = 0;
7805         *r->out.needed = 0;
7806         *r->out.info = NULL;
7807
7808         /* that's an [in out] buffer */
7809
7810         if (!r->in.buffer && (r->in.offered != 0) ) {
7811                 return WERR_INVALID_PARAM;
7812         }
7813
7814         DEBUG(4,("_spoolss_EnumForms\n"));
7815         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7816         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7817
7818         switch (r->in.level) {
7819         case 1:
7820                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7821                                                    get_session_info_system(),
7822                                                    p->msg_ctx,
7823                                                    r->out.count,
7824                                                    r->out.info);
7825                 break;
7826         default:
7827                 result = WERR_UNKNOWN_LEVEL;
7828                 break;
7829         }
7830
7831         if (!W_ERROR_IS_OK(result)) {
7832                 return result;
7833         }
7834
7835         if (*r->out.count == 0) {
7836                 return WERR_NO_MORE_ITEMS;
7837         }
7838
7839         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7840                                                      spoolss_EnumForms,
7841                                                      *r->out.info, r->in.level,
7842                                                      *r->out.count);
7843         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7844         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7845
7846         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7847 }
7848
7849 /****************************************************************
7850  _spoolss_GetForm
7851 ****************************************************************/
7852
7853 WERROR _spoolss_GetForm(struct pipes_struct *p,
7854                         struct spoolss_GetForm *r)
7855 {
7856         WERROR result;
7857
7858         /* that's an [in out] buffer */
7859
7860         if (!r->in.buffer && (r->in.offered != 0)) {
7861                 TALLOC_FREE(r->out.info);
7862                 return WERR_INVALID_PARAM;
7863         }
7864
7865         DEBUG(4,("_spoolss_GetForm\n"));
7866         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7867         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7868
7869         switch (r->in.level) {
7870         case 1:
7871                 result = winreg_printer_getform1_internal(p->mem_ctx,
7872                                                  get_session_info_system(),
7873                                                  p->msg_ctx,
7874                                                  r->in.form_name,
7875                                                  &r->out.info->info1);
7876                 break;
7877         default:
7878                 result = WERR_UNKNOWN_LEVEL;
7879                 break;
7880         }
7881
7882         if (!W_ERROR_IS_OK(result)) {
7883                 TALLOC_FREE(r->out.info);
7884                 return result;
7885         }
7886
7887         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7888                                                r->out.info, r->in.level);
7889         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7890
7891         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7892 }
7893
7894 /****************************************************************************
7895 ****************************************************************************/
7896
7897 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7898                           struct spoolss_PortInfo1 *r,
7899                           const char *name)
7900 {
7901         r->port_name = talloc_strdup(mem_ctx, name);
7902         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7903
7904         return WERR_OK;
7905 }
7906
7907 /****************************************************************************
7908  TODO: This probably needs distinguish between TCP/IP and Local ports
7909  somehow.
7910 ****************************************************************************/
7911
7912 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7913                           struct spoolss_PortInfo2 *r,
7914                           const char *name)
7915 {
7916         r->port_name = talloc_strdup(mem_ctx, name);
7917         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7918
7919         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7920         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7921
7922         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7923         W_ERROR_HAVE_NO_MEMORY(r->description);
7924
7925         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7926         r->reserved = 0;
7927
7928         return WERR_OK;
7929 }
7930
7931
7932 /****************************************************************************
7933  wrapper around the enumer ports command
7934 ****************************************************************************/
7935
7936 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7937 {
7938         char *cmd = lp_enumports_command(talloc_tos());
7939         char **qlines = NULL;
7940         char *command = NULL;
7941         int numlines;
7942         int ret;
7943         int fd;
7944
7945         *count = 0;
7946         *lines = NULL;
7947
7948         /* if no hook then just fill in the default port */
7949
7950         if ( !*cmd ) {
7951                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7952                         return WERR_NOMEM;
7953                 }
7954                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7955                         TALLOC_FREE(qlines);
7956                         return WERR_NOMEM;
7957                 }
7958                 qlines[1] = NULL;
7959                 numlines = 1;
7960         }
7961         else {
7962                 /* we have a valid enumport command */
7963
7964                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7965                 if (!command) {
7966                         return WERR_NOMEM;
7967                 }
7968
7969                 DEBUG(10,("Running [%s]\n", command));
7970                 ret = smbrun(command, &fd);
7971                 DEBUG(10,("Returned [%d]\n", ret));
7972                 TALLOC_FREE(command);
7973                 if (ret != 0) {
7974                         if (fd != -1) {
7975                                 close(fd);
7976                         }
7977                         return WERR_ACCESS_DENIED;
7978                 }
7979
7980                 numlines = 0;
7981                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7982                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7983                 close(fd);
7984         }
7985
7986         *count = numlines;
7987         *lines = qlines;
7988
7989         return WERR_OK;
7990 }
7991
7992 /****************************************************************************
7993  enumports level 1.
7994 ****************************************************************************/
7995
7996 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7997                                 union spoolss_PortInfo **info_p,
7998                                 uint32_t *count)
7999 {
8000         union spoolss_PortInfo *info = NULL;
8001         int i=0;
8002         WERROR result = WERR_OK;
8003         char **qlines = NULL;
8004         int numlines = 0;
8005
8006         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8007         if (!W_ERROR_IS_OK(result)) {
8008                 goto out;
8009         }
8010
8011         if (numlines) {
8012                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8013                 if (!info) {
8014                         DEBUG(10,("Returning WERR_NOMEM\n"));
8015                         result = WERR_NOMEM;
8016                         goto out;
8017                 }
8018
8019                 for (i=0; i<numlines; i++) {
8020                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8021                         result = fill_port_1(info, &info[i].info1, qlines[i]);
8022                         if (!W_ERROR_IS_OK(result)) {
8023                                 goto out;
8024                         }
8025                 }
8026         }
8027         TALLOC_FREE(qlines);
8028
8029 out:
8030         if (!W_ERROR_IS_OK(result)) {
8031                 TALLOC_FREE(info);
8032                 TALLOC_FREE(qlines);
8033                 *count = 0;
8034                 *info_p = NULL;
8035                 return result;
8036         }
8037
8038         *info_p = info;
8039         *count = numlines;
8040
8041         return WERR_OK;
8042 }
8043
8044 /****************************************************************************
8045  enumports level 2.
8046 ****************************************************************************/
8047
8048 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8049                                 union spoolss_PortInfo **info_p,
8050                                 uint32_t *count)
8051 {
8052         union spoolss_PortInfo *info = NULL;
8053         int i=0;
8054         WERROR result = WERR_OK;
8055         char **qlines = NULL;
8056         int numlines = 0;
8057
8058         result = enumports_hook(talloc_tos(), &numlines, &qlines );
8059         if (!W_ERROR_IS_OK(result)) {
8060                 goto out;
8061         }
8062
8063         if (numlines) {
8064                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8065                 if (!info) {
8066                         DEBUG(10,("Returning WERR_NOMEM\n"));
8067                         result = WERR_NOMEM;
8068                         goto out;
8069                 }
8070
8071                 for (i=0; i<numlines; i++) {
8072                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8073                         result = fill_port_2(info, &info[i].info2, qlines[i]);
8074                         if (!W_ERROR_IS_OK(result)) {
8075                                 goto out;
8076                         }
8077                 }
8078         }
8079         TALLOC_FREE(qlines);
8080
8081 out:
8082         if (!W_ERROR_IS_OK(result)) {
8083                 TALLOC_FREE(info);
8084                 TALLOC_FREE(qlines);
8085                 *count = 0;
8086                 *info_p = NULL;
8087                 return result;
8088         }
8089
8090         *info_p = info;
8091         *count = numlines;
8092
8093         return WERR_OK;
8094 }
8095
8096 /****************************************************************
8097  _spoolss_EnumPorts
8098 ****************************************************************/
8099
8100 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8101                           struct spoolss_EnumPorts *r)
8102 {
8103         WERROR result;
8104
8105         /* that's an [in out] buffer */
8106
8107         if (!r->in.buffer && (r->in.offered != 0)) {
8108                 return WERR_INVALID_PARAM;
8109         }
8110
8111         DEBUG(4,("_spoolss_EnumPorts\n"));
8112
8113         *r->out.count = 0;
8114         *r->out.needed = 0;
8115         *r->out.info = NULL;
8116
8117         switch (r->in.level) {
8118         case 1:
8119                 result = enumports_level_1(p->mem_ctx, r->out.info,
8120                                            r->out.count);
8121                 break;
8122         case 2:
8123                 result = enumports_level_2(p->mem_ctx, r->out.info,
8124                                            r->out.count);
8125                 break;
8126         default:
8127                 return WERR_UNKNOWN_LEVEL;
8128         }
8129
8130         if (!W_ERROR_IS_OK(result)) {
8131                 return result;
8132         }
8133
8134         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8135                                                      spoolss_EnumPorts,
8136                                                      *r->out.info, r->in.level,
8137                                                      *r->out.count);
8138         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8139         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8140
8141         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8142 }
8143
8144 /****************************************************************************
8145 ****************************************************************************/
8146
8147 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8148                                            const char *server,
8149                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8150                                            struct spoolss_DeviceMode *devmode,
8151                                            struct security_descriptor *secdesc,
8152                                            struct spoolss_UserLevelCtr *user_ctr,
8153                                            struct policy_handle *handle)
8154 {
8155         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8156         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8157         int     snum;
8158         WERROR err = WERR_OK;
8159
8160         /* samba does not have a concept of local, non-shared printers yet, so
8161          * make sure we always setup sharename - gd */
8162         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8163             (info2->printername != NULL && info2->printername[0] != '\0')) {
8164                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8165                         "no sharename has been set, setting printername %s as sharename\n",
8166                         info2->printername));
8167                 info2->sharename = info2->printername;
8168         }
8169
8170         /* check to see if the printer already exists */
8171         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8172                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8173                         info2->sharename));
8174                 return WERR_PRINTER_ALREADY_EXISTS;
8175         }
8176
8177         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8178                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8179                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8180                                 info2->printername));
8181                         return WERR_PRINTER_ALREADY_EXISTS;
8182                 }
8183         }
8184
8185         /* validate printer info struct */
8186         if (!info2->printername || strlen(info2->printername) == 0) {
8187                 return WERR_INVALID_PRINTER_NAME;
8188         }
8189         if (!info2->portname || strlen(info2->portname) == 0) {
8190                 return WERR_UNKNOWN_PORT;
8191         }
8192         if (!info2->drivername || strlen(info2->drivername) == 0) {
8193                 return WERR_UNKNOWN_PRINTER_DRIVER;
8194         }
8195         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8196                 return WERR_UNKNOWN_PRINTPROCESSOR;
8197         }
8198
8199         /* FIXME!!!  smbd should check to see if the driver is installed before
8200            trying to add a printer like this  --jerry */
8201
8202         if (*lp_addprinter_command(talloc_tos()) ) {
8203                 char *raddr;
8204
8205                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8206                                                          p->mem_ctx);
8207                 if (raddr == NULL) {
8208                         return WERR_NOMEM;
8209                 }
8210
8211                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8212                                        info2, raddr,
8213                                        p->msg_ctx) ) {
8214                         return WERR_ACCESS_DENIED;
8215                 }
8216         } else {
8217                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8218                         "smb.conf parameter \"addprinter command\" is defined. This "
8219                         "parameter must exist for this call to succeed\n",
8220                         info2->sharename ));
8221         }
8222
8223         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8224                 return WERR_ACCESS_DENIED;
8225         }
8226
8227         /* you must be a printer admin to add a new printer */
8228         if (!W_ERROR_IS_OK(print_access_check(p->session_info,
8229                                               p->msg_ctx,
8230                                               snum,
8231                                               PRINTER_ACCESS_ADMINISTER))) {
8232                 return WERR_ACCESS_DENIED;
8233         }
8234
8235         /*
8236          * Do sanity check on the requested changes for Samba.
8237          */
8238
8239         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8240                 return WERR_INVALID_PARAM;
8241         }
8242
8243         if (devmode == NULL) {
8244                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8245         }
8246
8247         err = update_dsspooler(p->mem_ctx,
8248                                get_session_info_system(),
8249                                p->msg_ctx,
8250                                0,
8251                                info2,
8252                                NULL);
8253         if (!W_ERROR_IS_OK(err)) {
8254                 return err;
8255         }
8256
8257         err = winreg_update_printer_internal(p->mem_ctx,
8258                                     get_session_info_system(),
8259                                     p->msg_ctx,
8260                                     info2->sharename,
8261                                     info2_mask,
8262                                     info2,
8263                                     devmode,
8264                                     secdesc);
8265         if (!W_ERROR_IS_OK(err)) {
8266                 return err;
8267         }
8268
8269         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8270         if (!W_ERROR_IS_OK(err)) {
8271                 /* Handle open failed - remove addition. */
8272                 ZERO_STRUCTP(handle);
8273                 return err;
8274         }
8275
8276         return WERR_OK;
8277 }
8278
8279 /****************************************************************
8280  _spoolss_AddPrinterEx
8281 ****************************************************************/
8282
8283 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8284                              struct spoolss_AddPrinterEx *r)
8285 {
8286         switch (r->in.info_ctr->level) {
8287         case 1:
8288                 /* we don't handle yet */
8289                 /* but I know what to do ... */
8290                 return WERR_UNKNOWN_LEVEL;
8291         case 2:
8292                 return spoolss_addprinterex_level_2(p, r->in.server,
8293                                                     r->in.info_ctr,
8294                                                     r->in.devmode_ctr->devmode,
8295                                                     r->in.secdesc_ctr->sd,
8296                                                     r->in.userlevel_ctr,
8297                                                     r->out.handle);
8298         default:
8299                 return WERR_UNKNOWN_LEVEL;
8300         }
8301 }
8302
8303 /****************************************************************
8304  _spoolss_AddPrinter
8305 ****************************************************************/
8306
8307 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8308                            struct spoolss_AddPrinter *r)
8309 {
8310         struct spoolss_AddPrinterEx a;
8311         struct spoolss_UserLevelCtr userlevel_ctr;
8312
8313         ZERO_STRUCT(userlevel_ctr);
8314
8315         userlevel_ctr.level = 1;
8316
8317         a.in.server             = r->in.server;
8318         a.in.info_ctr           = r->in.info_ctr;
8319         a.in.devmode_ctr        = r->in.devmode_ctr;
8320         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8321         a.in.userlevel_ctr      = &userlevel_ctr;
8322         a.out.handle            = r->out.handle;
8323
8324         return _spoolss_AddPrinterEx(p, &a);
8325 }
8326
8327 /****************************************************************
8328  _spoolss_AddPrinterDriverEx
8329 ****************************************************************/
8330
8331 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8332                                    struct spoolss_AddPrinterDriverEx *r)
8333 {
8334         WERROR err = WERR_OK;
8335         const char *driver_name = NULL;
8336         uint32_t version;
8337         const char *fn;
8338
8339         switch (p->opnum) {
8340                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8341                         fn = "_spoolss_AddPrinterDriver";
8342                         break;
8343                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8344                         fn = "_spoolss_AddPrinterDriverEx";
8345                         break;
8346                 default:
8347                         return WERR_INVALID_PARAM;
8348         }
8349
8350         /*
8351          * we only support the semantics of AddPrinterDriver()
8352          * i.e. only copy files that are newer than existing ones
8353          */
8354
8355         if (r->in.flags == 0) {
8356                 return WERR_INVALID_PARAM;
8357         }
8358
8359         if (r->in.flags != APD_COPY_NEW_FILES) {
8360                 return WERR_ACCESS_DENIED;
8361         }
8362
8363         /* FIXME */
8364         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8365                 /* Clever hack from Martin Zielinski <mz@seh.de>
8366                  * to allow downgrade from level 8 (Vista).
8367                  */
8368                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8369                         r->in.info_ctr->level));
8370                 return WERR_UNKNOWN_LEVEL;
8371         }
8372
8373         DEBUG(5,("Cleaning driver's information\n"));
8374         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8375         if (!W_ERROR_IS_OK(err))
8376                 goto done;
8377
8378         DEBUG(5,("Moving driver to final destination\n"));
8379         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8380         if (!W_ERROR_IS_OK(err)) {
8381                 goto done;
8382         }
8383
8384         err = winreg_add_driver_internal(p->mem_ctx,
8385                                 get_session_info_system(),
8386                                 p->msg_ctx,
8387                                 r->in.info_ctr,
8388                                 &driver_name,
8389                                 &version);
8390         if (!W_ERROR_IS_OK(err)) {
8391                 goto done;
8392         }
8393
8394         /*
8395          * I think this is where he DrvUpgradePrinter() hook would be
8396          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8397          * server.  Right now, we just need to send ourselves a message
8398          * to update each printer bound to this driver.   --jerry
8399          */
8400
8401         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8402                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8403                         fn, driver_name));
8404         }
8405
8406 done:
8407         return err;
8408 }
8409
8410 /****************************************************************
8411  _spoolss_AddPrinterDriver
8412 ****************************************************************/
8413
8414 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8415                                  struct spoolss_AddPrinterDriver *r)
8416 {
8417         struct spoolss_AddPrinterDriverEx a;
8418
8419         switch (r->in.info_ctr->level) {
8420         case 2:
8421         case 3:
8422         case 4:
8423         case 5:
8424                 break;
8425         default:
8426                 return WERR_UNKNOWN_LEVEL;
8427         }
8428
8429         a.in.servername         = r->in.servername;
8430         a.in.info_ctr           = r->in.info_ctr;
8431         a.in.flags              = APD_COPY_NEW_FILES;
8432
8433         return _spoolss_AddPrinterDriverEx(p, &a);
8434 }
8435
8436 /****************************************************************************
8437 ****************************************************************************/
8438
8439 struct _spoolss_paths {
8440         int type;
8441         const char *share;
8442         const char *dir;
8443 };
8444
8445 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8446
8447 static const struct _spoolss_paths spoolss_paths[]= {
8448         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8449         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8450 };
8451
8452 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8453                                           const char *servername,
8454                                           const char *environment,
8455                                           int component,
8456                                           char **path)
8457 {
8458         const char *pservername = NULL;
8459         const char *long_archi;
8460         const char *short_archi;
8461
8462         *path = NULL;
8463
8464         /* environment may be empty */
8465         if (environment && strlen(environment)) {
8466                 long_archi = environment;
8467         } else {
8468                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8469                                                   "spoolss", "architecture",
8470                                                   SPOOLSS_ARCHITECTURE_NT_X86);
8471         }
8472
8473         /* servername may be empty */
8474         if (servername && strlen(servername)) {
8475                 pservername = canon_servername(servername);
8476
8477                 if (!is_myname_or_ipaddr(pservername)) {
8478                         return WERR_INVALID_PARAM;
8479                 }
8480         }
8481
8482         if (!(short_archi = get_short_archi(long_archi))) {
8483                 return WERR_INVALID_ENVIRONMENT;
8484         }
8485
8486         switch (component) {
8487         case SPOOLSS_PRTPROCS_PATH:
8488         case SPOOLSS_DRIVER_PATH:
8489                 if (pservername) {
8490                         *path = talloc_asprintf(mem_ctx,
8491                                         "\\\\%s\\%s\\%s",
8492                                         pservername,
8493                                         spoolss_paths[component].share,
8494                                         short_archi);
8495                 } else {
8496                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8497                                         SPOOLSS_DEFAULT_SERVER_PATH,
8498                                         spoolss_paths[component].dir,
8499                                         short_archi);
8500                 }
8501                 break;
8502         default:
8503                 return WERR_INVALID_PARAM;
8504         }
8505
8506         if (!*path) {
8507                 return WERR_NOMEM;
8508         }
8509
8510         return WERR_OK;
8511 }
8512
8513 /****************************************************************************
8514 ****************************************************************************/
8515
8516 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8517                                           const char *servername,
8518                                           const char *environment,
8519                                           struct spoolss_DriverDirectoryInfo1 *r)
8520 {
8521         WERROR werr;
8522         char *path = NULL;
8523
8524         werr = compose_spoolss_server_path(mem_ctx,
8525                                            servername,
8526                                            environment,
8527                                            SPOOLSS_DRIVER_PATH,
8528                                            &path);
8529         if (!W_ERROR_IS_OK(werr)) {
8530                 return werr;
8531         }
8532
8533         DEBUG(4,("printer driver directory: [%s]\n", path));
8534
8535         r->directory_name = path;
8536
8537         return WERR_OK;
8538 }
8539
8540 /****************************************************************
8541  _spoolss_GetPrinterDriverDirectory
8542 ****************************************************************/
8543
8544 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8545                                           struct spoolss_GetPrinterDriverDirectory *r)
8546 {
8547         WERROR werror;
8548
8549         /* that's an [in out] buffer */
8550
8551         if (!r->in.buffer && (r->in.offered != 0)) {
8552                 TALLOC_FREE(r->out.info);
8553                 return WERR_INVALID_PARAM;
8554         }
8555
8556         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8557                 r->in.level));
8558
8559         *r->out.needed = 0;
8560
8561         /* r->in.level is ignored */
8562
8563         werror = getprinterdriverdir_level_1(p->mem_ctx,
8564                                              r->in.server,
8565                                              r->in.environment,
8566                                              &r->out.info->info1);
8567         if (!W_ERROR_IS_OK(werror)) {
8568                 TALLOC_FREE(r->out.info);
8569                 return werror;
8570         }
8571
8572         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8573                                                r->out.info, r->in.level);
8574         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8575
8576         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8577 }
8578
8579 /****************************************************************
8580  _spoolss_EnumPrinterData
8581 ****************************************************************/
8582
8583 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8584                                 struct spoolss_EnumPrinterData *r)
8585 {
8586         WERROR result;
8587         struct spoolss_EnumPrinterDataEx r2;
8588         uint32_t count;
8589         struct spoolss_PrinterEnumValues *info, *val = NULL;
8590         uint32_t needed;
8591
8592         r2.in.handle    = r->in.handle;
8593         r2.in.key_name  = "PrinterDriverData";
8594         r2.in.offered   = 0;
8595         r2.out.count    = &count;
8596         r2.out.info     = &info;
8597         r2.out.needed   = &needed;
8598
8599         result = _spoolss_EnumPrinterDataEx(p, &r2);
8600         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8601                 r2.in.offered = needed;
8602                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8603         }
8604         if (!W_ERROR_IS_OK(result)) {
8605                 return result;
8606         }
8607
8608         /*
8609          * The NT machine wants to know the biggest size of value and data
8610          *
8611          * cf: MSDN EnumPrinterData remark section
8612          */
8613
8614         if (!r->in.value_offered && !r->in.data_offered) {
8615                 uint32_t biggest_valuesize = 0;
8616                 uint32_t biggest_datasize = 0;
8617                 int i, name_length;
8618
8619                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8620
8621                 for (i=0; i<count; i++) {
8622
8623                         name_length = strlen(info[i].value_name);
8624                         if (strlen(info[i].value_name) > biggest_valuesize) {
8625                                 biggest_valuesize = name_length;
8626                         }
8627
8628                         if (info[i].data_length > biggest_datasize) {
8629                                 biggest_datasize = info[i].data_length;
8630                         }
8631
8632                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8633                                 biggest_datasize));
8634                 }
8635
8636                 /* the value is an UNICODE string but real_value_size is the length
8637                    in bytes including the trailing 0 */
8638
8639                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8640                 *r->out.data_needed  = biggest_datasize;
8641
8642                 DEBUG(6,("final values: [%d], [%d]\n",
8643                         *r->out.value_needed, *r->out.data_needed));
8644
8645                 return WERR_OK;
8646         }
8647
8648         if (r->in.enum_index < count) {
8649                 val = &info[r->in.enum_index];
8650         }
8651
8652         if (val == NULL) {
8653                 /* out_value should default to "" or else NT4 has
8654                    problems unmarshalling the response */
8655
8656                 if (r->in.value_offered) {
8657                         *r->out.value_needed = 1;
8658                         r->out.value_name = talloc_strdup(r, "");
8659                         if (!r->out.value_name) {
8660                                 return WERR_NOMEM;
8661                         }
8662                 } else {
8663                         r->out.value_name = NULL;
8664                         *r->out.value_needed = 0;
8665                 }
8666
8667                 /* the data is counted in bytes */
8668
8669                 *r->out.data_needed = r->in.data_offered;
8670
8671                 result = WERR_NO_MORE_ITEMS;
8672         } else {
8673                 /*
8674                  * the value is:
8675                  * - counted in bytes in the request
8676                  * - counted in UNICODE chars in the max reply
8677                  * - counted in bytes in the real size
8678                  *
8679                  * take a pause *before* coding not *during* coding
8680                  */
8681
8682                 /* name */
8683                 if (r->in.value_offered) {
8684                         r->out.value_name = talloc_strdup(r, val->value_name);
8685                         if (!r->out.value_name) {
8686                                 return WERR_NOMEM;
8687                         }
8688                         *r->out.value_needed = val->value_name_len;
8689                 } else {
8690                         r->out.value_name = NULL;
8691                         *r->out.value_needed = 0;
8692                 }
8693
8694                 /* type */
8695
8696                 *r->out.type = val->type;
8697
8698                 /* data - counted in bytes */
8699
8700                 /*
8701                  * See the section "Dynamically Typed Query Parameters"
8702                  * in MS-RPRN.
8703                  */
8704
8705                 if (r->out.data && val->data && val->data->data &&
8706                                 val->data_length && r->in.data_offered) {
8707                         memcpy(r->out.data, val->data->data,
8708                                 MIN(val->data_length,r->in.data_offered));
8709                 }
8710
8711                 *r->out.data_needed = val->data_length;
8712
8713                 result = WERR_OK;
8714         }
8715
8716         return result;
8717 }
8718
8719 /****************************************************************
8720  _spoolss_SetPrinterData
8721 ****************************************************************/
8722
8723 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8724                                struct spoolss_SetPrinterData *r)
8725 {
8726         struct spoolss_SetPrinterDataEx r2;
8727
8728         r2.in.handle            = r->in.handle;
8729         r2.in.key_name          = "PrinterDriverData";
8730         r2.in.value_name        = r->in.value_name;
8731         r2.in.type              = r->in.type;
8732         r2.in.data              = r->in.data;
8733         r2.in.offered           = r->in.offered;
8734
8735         return _spoolss_SetPrinterDataEx(p, &r2);
8736 }
8737
8738 /****************************************************************
8739  _spoolss_ResetPrinter
8740 ****************************************************************/
8741
8742 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8743                              struct spoolss_ResetPrinter *r)
8744 {
8745         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8746         int             snum;
8747
8748         DEBUG(5,("_spoolss_ResetPrinter\n"));
8749
8750         /*
8751          * All we do is to check to see if the handle and queue is valid.
8752          * This call really doesn't mean anything to us because we only
8753          * support RAW printing.   --jerry
8754          */
8755
8756         if (!Printer) {
8757                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8758                         OUR_HANDLE(r->in.handle)));
8759                 return WERR_BADFID;
8760         }
8761
8762         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8763                 return WERR_BADFID;
8764
8765
8766         /* blindly return success */
8767         return WERR_OK;
8768 }
8769
8770 /****************************************************************
8771  _spoolss_DeletePrinterData
8772 ****************************************************************/
8773
8774 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8775                                   struct spoolss_DeletePrinterData *r)
8776 {
8777         struct spoolss_DeletePrinterDataEx r2;
8778
8779         r2.in.handle            = r->in.handle;
8780         r2.in.key_name          = "PrinterDriverData";
8781         r2.in.value_name        = r->in.value_name;
8782
8783         return _spoolss_DeletePrinterDataEx(p, &r2);
8784 }
8785
8786 /****************************************************************
8787  _spoolss_AddForm
8788 ****************************************************************/
8789
8790 WERROR _spoolss_AddForm(struct pipes_struct *p,
8791                         struct spoolss_AddForm *r)
8792 {
8793         struct spoolss_AddFormInfo1 *form;
8794         int snum = -1;
8795         WERROR status = WERR_OK;
8796         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8797         struct dcerpc_binding_handle *b;
8798         TALLOC_CTX *tmp_ctx = NULL;
8799
8800         DEBUG(5,("_spoolss_AddForm\n"));
8801
8802         if (!Printer) {
8803                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8804                         OUR_HANDLE(r->in.handle)));
8805                 return WERR_BADFID;
8806         }
8807
8808         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8809            and not a printer admin, then fail */
8810
8811         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8812             !security_token_has_privilege(p->session_info->security_token,
8813                                           SEC_PRIV_PRINT_OPERATOR)) {
8814                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8815                 return WERR_ACCESS_DENIED;
8816         }
8817
8818         if (r->in.info_ctr->level != 1) {
8819                 return WERR_INVALID_LEVEL;
8820         }
8821
8822         form = r->in.info_ctr->info.info1;
8823         if (!form) {
8824                 return WERR_INVALID_PARAM;
8825         }
8826
8827         switch (form->flags) {
8828         case SPOOLSS_FORM_USER:
8829         case SPOOLSS_FORM_BUILTIN:
8830         case SPOOLSS_FORM_PRINTER:
8831                 break;
8832         default:
8833                 return WERR_INVALID_PARAM;
8834         }
8835
8836         tmp_ctx = talloc_new(p->mem_ctx);
8837         if (!tmp_ctx) {
8838                 return WERR_NOMEM;
8839         }
8840
8841         status = winreg_printer_binding_handle(tmp_ctx,
8842                                                get_session_info_system(),
8843                                                p->msg_ctx,
8844                                                &b);
8845         if (!W_ERROR_IS_OK(status)) {
8846                 goto done;
8847         }
8848
8849         status = winreg_printer_addform1(tmp_ctx, b, form);
8850         if (!W_ERROR_IS_OK(status)) {
8851                 goto done;
8852         }
8853
8854         /*
8855          * ChangeID must always be set if this is a printer
8856          */
8857         if (Printer->printer_type == SPLHND_PRINTER) {
8858                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8859                         status = WERR_BADFID;
8860                         goto done;
8861                 }
8862
8863                 status = winreg_printer_update_changeid(tmp_ctx, b,
8864                                                         lp_const_servicename(snum));
8865         }
8866
8867 done:
8868         talloc_free(tmp_ctx);
8869         return status;
8870 }
8871
8872 /****************************************************************
8873  _spoolss_DeleteForm
8874 ****************************************************************/
8875
8876 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8877                            struct spoolss_DeleteForm *r)
8878 {
8879         const char *form_name = r->in.form_name;
8880         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8881         int snum = -1;
8882         WERROR status = WERR_OK;
8883         struct dcerpc_binding_handle *b;
8884         TALLOC_CTX *tmp_ctx = NULL;
8885
8886         DEBUG(5,("_spoolss_DeleteForm\n"));
8887
8888         if (!Printer) {
8889                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8890                         OUR_HANDLE(r->in.handle)));
8891                 return WERR_BADFID;
8892         }
8893
8894         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8895             !security_token_has_privilege(p->session_info->security_token,
8896                                           SEC_PRIV_PRINT_OPERATOR)) {
8897                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8898                 return WERR_ACCESS_DENIED;
8899         }
8900
8901         tmp_ctx = talloc_new(p->mem_ctx);
8902         if (!tmp_ctx) {
8903                 return WERR_NOMEM;
8904         }
8905
8906         status = winreg_printer_binding_handle(tmp_ctx,
8907                                                get_session_info_system(),
8908                                                p->msg_ctx,
8909                                                &b);
8910         if (!W_ERROR_IS_OK(status)) {
8911                 goto done;
8912         }
8913
8914         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8915         if (!W_ERROR_IS_OK(status)) {
8916                 goto done;
8917         }
8918
8919         /*
8920          * ChangeID must always be set if this is a printer
8921          */
8922         if (Printer->printer_type == SPLHND_PRINTER) {
8923                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8924                         status = WERR_BADFID;
8925                         goto done;
8926                 }
8927
8928                 status = winreg_printer_update_changeid(tmp_ctx, b,
8929                                                         lp_const_servicename(snum));
8930         }
8931
8932 done:
8933         talloc_free(tmp_ctx);
8934         return status;
8935 }
8936
8937 /****************************************************************
8938  _spoolss_SetForm
8939 ****************************************************************/
8940
8941 WERROR _spoolss_SetForm(struct pipes_struct *p,
8942                         struct spoolss_SetForm *r)
8943 {
8944         struct spoolss_AddFormInfo1 *form;
8945         const char *form_name = r->in.form_name;
8946         int snum = -1;
8947         WERROR status = WERR_OK;
8948         struct dcerpc_binding_handle *b;
8949         TALLOC_CTX *tmp_ctx = NULL;
8950
8951         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8952
8953         DEBUG(5,("_spoolss_SetForm\n"));
8954
8955         if (!Printer) {
8956                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8957                         OUR_HANDLE(r->in.handle)));
8958                 return WERR_BADFID;
8959         }
8960
8961         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8962            and not a printer admin, then fail */
8963
8964         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8965              !security_token_has_privilege(p->session_info->security_token,
8966                                            SEC_PRIV_PRINT_OPERATOR)) {
8967                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8968                 return WERR_ACCESS_DENIED;
8969         }
8970
8971         if (r->in.info_ctr->level != 1) {
8972                 return WERR_INVALID_LEVEL;
8973         }
8974
8975         form = r->in.info_ctr->info.info1;
8976         if (!form) {
8977                 return WERR_INVALID_PARAM;
8978         }
8979
8980         tmp_ctx = talloc_new(p->mem_ctx);
8981         if (!tmp_ctx) {
8982                 return WERR_NOMEM;
8983         }
8984
8985         status = winreg_printer_binding_handle(tmp_ctx,
8986                                                get_session_info_system(),
8987                                                p->msg_ctx,
8988                                                &b);
8989         if (!W_ERROR_IS_OK(status)) {
8990                 goto done;
8991         }
8992
8993         status = winreg_printer_setform1(tmp_ctx, b,
8994                                          form_name,
8995                                          form);
8996         if (!W_ERROR_IS_OK(status)) {
8997                 goto done;
8998         }
8999
9000         /*
9001          * ChangeID must always be set if this is a printer
9002          */
9003         if (Printer->printer_type == SPLHND_PRINTER) {
9004                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9005                         status = WERR_BADFID;
9006                         goto done;
9007                 }
9008
9009                 status = winreg_printer_update_changeid(tmp_ctx, b,
9010                                                         lp_const_servicename(snum));
9011         }
9012
9013 done:
9014         talloc_free(tmp_ctx);
9015         return status;
9016 }
9017
9018 /****************************************************************************
9019  fill_print_processor1
9020 ****************************************************************************/
9021
9022 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9023                                     struct spoolss_PrintProcessorInfo1 *r,
9024                                     const char *print_processor_name)
9025 {
9026         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9027         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9028
9029         return WERR_OK;
9030 }
9031
9032 /****************************************************************************
9033  enumprintprocessors level 1.
9034 ****************************************************************************/
9035
9036 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9037                                           union spoolss_PrintProcessorInfo **info_p,
9038                                           uint32_t *count)
9039 {
9040         union spoolss_PrintProcessorInfo *info;
9041         WERROR result;
9042
9043         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9044         W_ERROR_HAVE_NO_MEMORY(info);
9045
9046         *count = 1;
9047
9048         result = fill_print_processor1(info, &info[0].info1, "winprint");
9049         if (!W_ERROR_IS_OK(result)) {
9050                 goto out;
9051         }
9052
9053  out:
9054         if (!W_ERROR_IS_OK(result)) {
9055                 TALLOC_FREE(info);
9056                 *count = 0;
9057                 return result;
9058         }
9059
9060         *info_p = info;
9061
9062         return WERR_OK;
9063 }
9064
9065 /****************************************************************
9066  _spoolss_EnumPrintProcessors
9067 ****************************************************************/
9068
9069 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9070                                     struct spoolss_EnumPrintProcessors *r)
9071 {
9072         WERROR result;
9073
9074         /* that's an [in out] buffer */
9075
9076         if (!r->in.buffer && (r->in.offered != 0)) {
9077                 return WERR_INVALID_PARAM;
9078         }
9079
9080         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9081
9082         /*
9083          * Enumerate the print processors ...
9084          *
9085          * Just reply with "winprint", to keep NT happy
9086          * and I can use my nice printer checker.
9087          */
9088
9089         *r->out.count = 0;
9090         *r->out.needed = 0;
9091         *r->out.info = NULL;
9092
9093         if (!get_short_archi(r->in.environment)) {
9094                 return WERR_INVALID_ENVIRONMENT;
9095         }
9096
9097         switch (r->in.level) {
9098         case 1:
9099                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9100                                                      r->out.count);
9101                 break;
9102         default:
9103                 return WERR_UNKNOWN_LEVEL;
9104         }
9105
9106         if (!W_ERROR_IS_OK(result)) {
9107                 return result;
9108         }
9109
9110         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9111                                                      spoolss_EnumPrintProcessors,
9112                                                      *r->out.info, r->in.level,
9113                                                      *r->out.count);
9114         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9115         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9116
9117         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9118 }
9119
9120 /****************************************************************************
9121  fill_printprocdatatype1
9122 ****************************************************************************/
9123
9124 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9125                                       struct spoolss_PrintProcDataTypesInfo1 *r,
9126                                       const char *name_array)
9127 {
9128         r->name_array = talloc_strdup(mem_ctx, name_array);
9129         W_ERROR_HAVE_NO_MEMORY(r->name_array);
9130
9131         return WERR_OK;
9132 }
9133
9134 /****************************************************************************
9135  enumprintprocdatatypes level 1.
9136 ****************************************************************************/
9137
9138 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9139                                              union spoolss_PrintProcDataTypesInfo **info_p,
9140                                              uint32_t *count)
9141 {
9142         WERROR result;
9143         union spoolss_PrintProcDataTypesInfo *info;
9144
9145         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9146         W_ERROR_HAVE_NO_MEMORY(info);
9147
9148         *count = 1;
9149
9150         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9151         if (!W_ERROR_IS_OK(result)) {
9152                 goto out;
9153         }
9154
9155  out:
9156         if (!W_ERROR_IS_OK(result)) {
9157                 TALLOC_FREE(info);
9158                 *count = 0;
9159                 return result;
9160         }
9161
9162         *info_p = info;
9163
9164         return WERR_OK;
9165 }
9166
9167 /****************************************************************
9168  _spoolss_EnumPrintProcDataTypes
9169 ****************************************************************/
9170
9171 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9172                                        struct spoolss_EnumPrintProcDataTypes *r)
9173 {
9174         WERROR result;
9175
9176         /* that's an [in out] buffer */
9177
9178         if (!r->in.buffer && (r->in.offered != 0)) {
9179                 return WERR_INVALID_PARAM;
9180         }
9181
9182         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9183
9184         *r->out.count = 0;
9185         *r->out.needed = 0;
9186         *r->out.info = NULL;
9187
9188         if (r->in.print_processor_name == NULL ||
9189             !strequal(r->in.print_processor_name, "winprint")) {
9190                 return WERR_UNKNOWN_PRINTPROCESSOR;
9191         }
9192
9193         switch (r->in.level) {
9194         case 1:
9195                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9196                                                         r->out.count);
9197                 break;
9198         default:
9199                 return WERR_UNKNOWN_LEVEL;
9200         }
9201
9202         if (!W_ERROR_IS_OK(result)) {
9203                 return result;
9204         }
9205
9206         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9207                                                      spoolss_EnumPrintProcDataTypes,
9208                                                      *r->out.info, r->in.level,
9209                                                      *r->out.count);
9210         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9211         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9212
9213         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9214 }
9215
9216 /****************************************************************************
9217  fill_monitor_1
9218 ****************************************************************************/
9219
9220 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9221                              struct spoolss_MonitorInfo1 *r,
9222                              const char *monitor_name)
9223 {
9224         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9225         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9226
9227         return WERR_OK;
9228 }
9229
9230 /****************************************************************************
9231  fill_monitor_2
9232 ****************************************************************************/
9233
9234 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9235                              struct spoolss_MonitorInfo2 *r,
9236                              const char *monitor_name,
9237                              const char *environment,
9238                              const char *dll_name)
9239 {
9240         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9241         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9242         r->environment                  = talloc_strdup(mem_ctx, environment);
9243         W_ERROR_HAVE_NO_MEMORY(r->environment);
9244         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9245         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9246
9247         return WERR_OK;
9248 }
9249
9250 /****************************************************************************
9251  enumprintmonitors level 1.
9252 ****************************************************************************/
9253
9254 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9255                                         union spoolss_MonitorInfo **info_p,
9256                                         uint32_t *count)
9257 {
9258         union spoolss_MonitorInfo *info;
9259         WERROR result = WERR_OK;
9260
9261         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9262         W_ERROR_HAVE_NO_MEMORY(info);
9263
9264         *count = 2;
9265
9266         result = fill_monitor_1(info, &info[0].info1,
9267                                 SPL_LOCAL_PORT);
9268         if (!W_ERROR_IS_OK(result)) {
9269                 goto out;
9270         }
9271
9272         result = fill_monitor_1(info, &info[1].info1,
9273                                 SPL_TCPIP_PORT);
9274         if (!W_ERROR_IS_OK(result)) {
9275                 goto out;
9276         }
9277
9278 out:
9279         if (!W_ERROR_IS_OK(result)) {
9280                 TALLOC_FREE(info);
9281                 *count = 0;
9282                 return result;
9283         }
9284
9285         *info_p = info;
9286
9287         return WERR_OK;
9288 }
9289
9290 /****************************************************************************
9291  enumprintmonitors level 2.
9292 ****************************************************************************/
9293
9294 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9295                                         union spoolss_MonitorInfo **info_p,
9296                                         uint32_t *count)
9297 {
9298         union spoolss_MonitorInfo *info;
9299         WERROR result = WERR_OK;
9300
9301         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9302         W_ERROR_HAVE_NO_MEMORY(info);
9303
9304         *count = 2;
9305
9306         result = fill_monitor_2(info, &info[0].info2,
9307                                 SPL_LOCAL_PORT,
9308                                 "Windows NT X86", /* FIXME */
9309                                 "localmon.dll");
9310         if (!W_ERROR_IS_OK(result)) {
9311                 goto out;
9312         }
9313
9314         result = fill_monitor_2(info, &info[1].info2,
9315                                 SPL_TCPIP_PORT,
9316                                 "Windows NT X86", /* FIXME */
9317                                 "tcpmon.dll");
9318         if (!W_ERROR_IS_OK(result)) {
9319                 goto out;
9320         }
9321
9322 out:
9323         if (!W_ERROR_IS_OK(result)) {
9324                 TALLOC_FREE(info);
9325                 *count = 0;
9326                 return result;
9327         }
9328
9329         *info_p = info;
9330
9331         return WERR_OK;
9332 }
9333
9334 /****************************************************************
9335  _spoolss_EnumMonitors
9336 ****************************************************************/
9337
9338 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9339                              struct spoolss_EnumMonitors *r)
9340 {
9341         WERROR result;
9342
9343         /* that's an [in out] buffer */
9344
9345         if (!r->in.buffer && (r->in.offered != 0)) {
9346                 return WERR_INVALID_PARAM;
9347         }
9348
9349         DEBUG(5,("_spoolss_EnumMonitors\n"));
9350
9351         /*
9352          * Enumerate the print monitors ...
9353          *
9354          * Just reply with "Local Port", to keep NT happy
9355          * and I can use my nice printer checker.
9356          */
9357
9358         *r->out.count = 0;
9359         *r->out.needed = 0;
9360         *r->out.info = NULL;
9361
9362         switch (r->in.level) {
9363         case 1:
9364                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9365                                                    r->out.count);
9366                 break;
9367         case 2:
9368                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9369                                                    r->out.count);
9370                 break;
9371         default:
9372                 return WERR_UNKNOWN_LEVEL;
9373         }
9374
9375         if (!W_ERROR_IS_OK(result)) {
9376                 return result;
9377         }
9378
9379         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9380                                                      spoolss_EnumMonitors,
9381                                                      *r->out.info, r->in.level,
9382                                                      *r->out.count);
9383         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9384         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9385
9386         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9387 }
9388
9389 /****************************************************************************
9390 ****************************************************************************/
9391
9392 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9393                              const print_queue_struct *queue,
9394                              int count, int snum,
9395                              struct spoolss_PrinterInfo2 *pinfo2,
9396                              uint32_t jobid,
9397                              int sysjob,
9398                              struct spoolss_JobInfo1 *r)
9399 {
9400         int i = 0;
9401         bool found = false;
9402
9403         for (i=0; i<count; i++) {
9404                 if (queue[i].sysjob == sysjob) {
9405                         found = true;
9406                         break;
9407                 }
9408         }
9409
9410         if (found == false) {
9411                 /* NT treats not found as bad param... yet another bad choice */
9412                 return WERR_INVALID_PARAM;
9413         }
9414
9415         return fill_job_info1(mem_ctx,
9416                               r,
9417                               &queue[i],
9418                               jobid,
9419                               i,
9420                               snum,
9421                               pinfo2);
9422 }
9423
9424 /****************************************************************************
9425 ****************************************************************************/
9426
9427 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9428                              const print_queue_struct *queue,
9429                              int count, int snum,
9430                              struct spoolss_PrinterInfo2 *pinfo2,
9431                              uint32_t jobid,
9432                              int sysjob,
9433                              struct spoolss_JobInfo2 *r)
9434 {
9435         int i = 0;
9436         bool found = false;
9437         struct spoolss_DeviceMode *devmode;
9438         WERROR result;
9439
9440         for (i=0; i<count; i++) {
9441                 if (queue[i].sysjob == sysjob) {
9442                         found = true;
9443                         break;
9444                 }
9445         }
9446
9447         if (found == false) {
9448                 /* NT treats not found as bad param... yet another bad
9449                    choice */
9450                 return WERR_INVALID_PARAM;
9451         }
9452
9453         /*
9454          * if the print job does not have a DEVMODE associated with it,
9455          * just use the one for the printer. A NULL devicemode is not
9456          *  a failure condition
9457          */
9458
9459         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9460         if (!devmode) {
9461                 result = spoolss_create_default_devmode(mem_ctx,
9462                                                 pinfo2->printername,
9463                                                 &devmode);
9464                 if (!W_ERROR_IS_OK(result)) {
9465                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9466                         return result;
9467                 }
9468         }
9469
9470         return fill_job_info2(mem_ctx,
9471                               r,
9472                               &queue[i],
9473                               jobid,
9474                               i,
9475                               snum,
9476                               pinfo2,
9477                               devmode);
9478 }
9479
9480 /****************************************************************
9481  _spoolss_GetJob
9482 ****************************************************************/
9483
9484 WERROR _spoolss_GetJob(struct pipes_struct *p,
9485                        struct spoolss_GetJob *r)
9486 {
9487         WERROR result = WERR_OK;
9488         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9489         const char *svc_name;
9490         int sysjob;
9491         int snum;
9492         int count;
9493         struct tdb_print_db *pdb;
9494         print_queue_struct      *queue = NULL;
9495         print_status_struct prt_status;
9496
9497         /* that's an [in out] buffer */
9498
9499         if (!r->in.buffer && (r->in.offered != 0)) {
9500                 result = WERR_INVALID_PARAM;
9501                 goto err_jinfo_free;
9502         }
9503
9504         DEBUG(5,("_spoolss_GetJob\n"));
9505
9506         *r->out.needed = 0;
9507
9508         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9509                 result = WERR_BADFID;
9510                 goto err_jinfo_free;
9511         }
9512
9513         svc_name = lp_const_servicename(snum);
9514         if (svc_name == NULL) {
9515                 result = WERR_INVALID_PARAM;
9516                 goto err_jinfo_free;
9517         }
9518
9519         result = winreg_get_printer_internal(p->mem_ctx,
9520                                     get_session_info_system(),
9521                                     p->msg_ctx,
9522                                     svc_name,
9523                                     &pinfo2);
9524         if (!W_ERROR_IS_OK(result)) {
9525                 goto err_jinfo_free;
9526         }
9527
9528         pdb = get_print_db_byname(svc_name);
9529         if (pdb == NULL) {
9530                 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9531                 result = WERR_INVALID_PARAM;
9532                 goto err_pinfo_free;
9533         }
9534
9535         sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9536         release_print_db(pdb);
9537         if (sysjob == -1) {
9538                 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9539                 result = WERR_INVALID_PARAM;
9540                 goto err_pinfo_free;
9541         }
9542
9543         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9544
9545         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9546                      count, prt_status.status, prt_status.message));
9547
9548         switch (r->in.level) {
9549         case 1:
9550                 result = getjob_level_1(p->mem_ctx,
9551                                         queue, count, snum, pinfo2,
9552                                         r->in.job_id, sysjob,
9553                                         &r->out.info->info1);
9554                 break;
9555         case 2:
9556                 result = getjob_level_2(p->mem_ctx,
9557                                         queue, count, snum, pinfo2,
9558                                         r->in.job_id, sysjob,
9559                                         &r->out.info->info2);
9560                 break;
9561         default:
9562                 result = WERR_UNKNOWN_LEVEL;
9563                 break;
9564         }
9565
9566         SAFE_FREE(queue);
9567         TALLOC_FREE(pinfo2);
9568
9569         if (!W_ERROR_IS_OK(result)) {
9570                 goto err_jinfo_free;
9571         }
9572
9573         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9574                                                                                    r->in.level);
9575         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9576
9577         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9578
9579 err_pinfo_free:
9580         TALLOC_FREE(pinfo2);
9581 err_jinfo_free:
9582         TALLOC_FREE(r->out.info);
9583         return result;
9584 }
9585
9586 /****************************************************************
9587  _spoolss_GetPrinterDataEx
9588 ****************************************************************/
9589
9590 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9591                                  struct spoolss_GetPrinterDataEx *r)
9592 {
9593
9594         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9595         const char *printer;
9596         int                     snum = 0;
9597         WERROR result = WERR_OK;
9598         DATA_BLOB blob;
9599         enum winreg_Type val_type = REG_NONE;
9600         uint8_t *val_data = NULL;
9601         uint32_t val_size = 0;
9602         struct dcerpc_binding_handle *b;
9603         TALLOC_CTX *tmp_ctx;
9604
9605         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9606
9607         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9608                 r->in.key_name, r->in.value_name));
9609
9610         /* in case of problem, return some default values */
9611
9612         *r->out.needed  = 0;
9613         *r->out.type    = REG_NONE;
9614
9615         tmp_ctx = talloc_new(p->mem_ctx);
9616         if (!tmp_ctx) {
9617                 return WERR_NOMEM;
9618         }
9619
9620         if (!Printer) {
9621                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9622                         OUR_HANDLE(r->in.handle)));
9623                 result = WERR_BADFID;
9624                 goto done;
9625         }
9626
9627         /* check to see if the keyname is valid */
9628         if (!strlen(r->in.key_name)) {
9629                 result = WERR_INVALID_PARAM;
9630                 goto done;
9631         }
9632
9633         /* Is the handle to a printer or to the server? */
9634
9635         if (Printer->printer_type == SPLHND_SERVER) {
9636
9637                 union spoolss_PrinterData data;
9638
9639                 result = getprinterdata_printer_server(tmp_ctx,
9640                                                        r->in.value_name,
9641                                                        r->out.type,
9642                                                        &data);
9643                 if (!W_ERROR_IS_OK(result)) {
9644                         goto done;
9645                 }
9646
9647                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9648                                                   *r->out.type, &data);
9649                 if (!W_ERROR_IS_OK(result)) {
9650                         goto done;
9651                 }
9652
9653                 *r->out.needed = blob.length;
9654
9655                 if (r->in.offered >= *r->out.needed) {
9656                         memcpy(r->out.data, blob.data, blob.length);
9657                 }
9658
9659                 result = WERR_OK;
9660                 goto done;
9661         }
9662
9663         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9664                 result = WERR_BADFID;
9665                 goto done;
9666         }
9667         printer = lp_const_servicename(snum);
9668
9669         result = winreg_printer_binding_handle(tmp_ctx,
9670                                                get_session_info_system(),
9671                                                p->msg_ctx,
9672                                                &b);
9673         if (!W_ERROR_IS_OK(result)) {
9674                 goto done;
9675         }
9676
9677         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9678         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9679             strequal(r->in.value_name, "ChangeId")) {
9680                 *r->out.type = REG_DWORD;
9681                 *r->out.needed = 4;
9682                 if (r->in.offered >= *r->out.needed) {
9683                         uint32_t changeid = 0;
9684
9685                         result = winreg_printer_get_changeid(tmp_ctx, b,
9686                                                              printer,
9687                                                              &changeid);
9688                         if (!W_ERROR_IS_OK(result)) {
9689                                 goto done;
9690                         }
9691
9692                         SIVAL(r->out.data, 0, changeid);
9693                         result = WERR_OK;
9694                 }
9695                 goto done;
9696         }
9697
9698         result = winreg_get_printer_dataex(tmp_ctx, b,
9699                                            printer,
9700                                            r->in.key_name,
9701                                            r->in.value_name,
9702                                            &val_type,
9703                                            &val_data,
9704                                            &val_size);
9705         if (!W_ERROR_IS_OK(result)) {
9706                 goto done;
9707         }
9708
9709         *r->out.needed = val_size;
9710         *r->out.type = val_type;
9711
9712         if (r->in.offered >= *r->out.needed) {
9713                 memcpy(r->out.data, val_data, val_size);
9714         }
9715
9716 done:
9717         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9718
9719         if (W_ERROR_IS_OK(result)) {
9720                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9721         }
9722
9723         talloc_free(tmp_ctx);
9724         return result;
9725 }
9726
9727 /****************************************************************
9728  _spoolss_SetPrinterDataEx
9729 ****************************************************************/
9730
9731 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9732                                  struct spoolss_SetPrinterDataEx *r)
9733 {
9734         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9735         int                     snum = 0;
9736         WERROR                  result = WERR_OK;
9737         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9738         char                    *oid_string;
9739         struct dcerpc_binding_handle *b;
9740         TALLOC_CTX *tmp_ctx;
9741
9742         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9743
9744         /* From MSDN documentation of SetPrinterDataEx: pass request to
9745            SetPrinterData if key is "PrinterDriverData" */
9746
9747         if (!Printer) {
9748                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9749                         OUR_HANDLE(r->in.handle)));
9750                 return WERR_BADFID;
9751         }
9752
9753         if (Printer->printer_type == SPLHND_SERVER) {
9754                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9755                         "Not implemented for server handles yet\n"));
9756                 return WERR_INVALID_PARAM;
9757         }
9758
9759         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9760                 return WERR_BADFID;
9761         }
9762
9763         /*
9764          * Access check : NT returns "access denied" if you make a
9765          * SetPrinterData call without the necessary privildge.
9766          * we were originally returning OK if nothing changed
9767          * which made Win2k issue **a lot** of SetPrinterData
9768          * when connecting to a printer  --jerry
9769          */
9770
9771         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9772                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9773                         "change denied by handle access permissions\n"));
9774                 return WERR_ACCESS_DENIED;
9775         }
9776
9777         tmp_ctx = talloc_new(p->mem_ctx);
9778         if (!tmp_ctx) {
9779                 return WERR_NOMEM;
9780         }
9781
9782         result = winreg_printer_binding_handle(tmp_ctx,
9783                                                get_session_info_system(),
9784                                                p->msg_ctx,
9785                                                &b);
9786         if (!W_ERROR_IS_OK(result)) {
9787                 goto done;
9788         }
9789
9790         result = winreg_get_printer(tmp_ctx, b,
9791                                     lp_servicename(talloc_tos(), snum),
9792                                     &pinfo2);
9793         if (!W_ERROR_IS_OK(result)) {
9794                 goto done;
9795         }
9796
9797         /* check for OID in valuename */
9798
9799         oid_string = strchr(r->in.value_name, ',');
9800         if (oid_string) {
9801                 *oid_string = '\0';
9802                 oid_string++;
9803         }
9804
9805         /* save the registry data */
9806
9807         result = winreg_set_printer_dataex(tmp_ctx, b,
9808                                            pinfo2->sharename,
9809                                            r->in.key_name,
9810                                            r->in.value_name,
9811                                            r->in.type,
9812                                            r->in.data,
9813                                            r->in.offered);
9814
9815         if (W_ERROR_IS_OK(result)) {
9816                 /* save the OID if one was specified */
9817                 if (oid_string) {
9818                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9819                                 r->in.key_name, SPOOL_OID_KEY);
9820                         if (!str) {
9821                                 result = WERR_NOMEM;
9822                                 goto done;
9823                         }
9824
9825                         /*
9826                          * I'm not checking the status here on purpose.  Don't know
9827                          * if this is right, but I'm returning the status from the
9828                          * previous set_printer_dataex() call.  I have no idea if
9829                          * this is right.    --jerry
9830                          */
9831                         winreg_set_printer_dataex(tmp_ctx, b,
9832                                                   pinfo2->sharename,
9833                                                   str,
9834                                                   r->in.value_name,
9835                                                   REG_SZ,
9836                                                   (uint8_t *) oid_string,
9837                                                   strlen(oid_string) + 1);
9838                 }
9839
9840                 result = winreg_printer_update_changeid(tmp_ctx, b,
9841                                                         lp_const_servicename(snum));
9842
9843         }
9844
9845 done:
9846         talloc_free(tmp_ctx);
9847         return result;
9848 }
9849
9850 /****************************************************************
9851  _spoolss_DeletePrinterDataEx
9852 ****************************************************************/
9853
9854 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9855                                     struct spoolss_DeletePrinterDataEx *r)
9856 {
9857         const char *printer;
9858         int             snum=0;
9859         WERROR          status = WERR_OK;
9860         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9861
9862         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9863
9864         if (!Printer) {
9865                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9866                         "Invalid handle (%s:%u:%u).\n",
9867                         OUR_HANDLE(r->in.handle)));
9868                 return WERR_BADFID;
9869         }
9870
9871         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9872                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9873                         "printer properties change denied by handle\n"));
9874                 return WERR_ACCESS_DENIED;
9875         }
9876
9877         if (!r->in.value_name || !r->in.key_name) {
9878                 return WERR_NOMEM;
9879         }
9880
9881         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9882                 return WERR_BADFID;
9883         }
9884         printer = lp_const_servicename(snum);
9885
9886         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9887                                               get_session_info_system(),
9888                                               p->msg_ctx,
9889                                               printer,
9890                                               r->in.key_name,
9891                                               r->in.value_name);
9892         if (W_ERROR_IS_OK(status)) {
9893                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9894                                                         get_session_info_system(),
9895                                                         p->msg_ctx,
9896                                                         printer);
9897         }
9898
9899         return status;
9900 }
9901
9902 /****************************************************************
9903  _spoolss_EnumPrinterKey
9904 ****************************************************************/
9905
9906 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9907                                struct spoolss_EnumPrinterKey *r)
9908 {
9909         uint32_t        num_keys;
9910         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9911         int             snum = 0;
9912         WERROR          result = WERR_BADFILE;
9913         const char **array = NULL;
9914         DATA_BLOB blob;
9915
9916         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9917
9918         if (!Printer) {
9919                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9920                         OUR_HANDLE(r->in.handle)));
9921                 return WERR_BADFID;
9922         }
9923
9924         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9925                 return WERR_BADFID;
9926         }
9927
9928         result = winreg_enum_printer_key_internal(p->mem_ctx,
9929                                          get_session_info_system(),
9930                                          p->msg_ctx,
9931                                          lp_const_servicename(snum),
9932                                          r->in.key_name,
9933                                          &num_keys,
9934                                          &array);
9935         if (!W_ERROR_IS_OK(result)) {
9936                 goto done;
9937         }
9938
9939         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9940                 result = WERR_NOMEM;
9941                 goto done;
9942         }
9943
9944         *r->out._ndr_size = r->in.offered / 2;
9945         *r->out.needed = blob.length;
9946
9947         if (r->in.offered < *r->out.needed) {
9948                 result = WERR_MORE_DATA;
9949         } else {
9950                 result = WERR_OK;
9951                 r->out.key_buffer->string_array = array;
9952         }
9953
9954  done:
9955         if (!W_ERROR_IS_OK(result)) {
9956                 TALLOC_FREE(array);
9957                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9958                         *r->out.needed = 0;
9959                 }
9960         }
9961
9962         return result;
9963 }
9964
9965 /****************************************************************
9966  _spoolss_DeletePrinterKey
9967 ****************************************************************/
9968
9969 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9970                                  struct spoolss_DeletePrinterKey *r)
9971 {
9972         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9973         int                     snum=0;
9974         WERROR                  status;
9975         const char *printer;
9976         struct dcerpc_binding_handle *b;
9977         TALLOC_CTX *tmp_ctx;
9978
9979         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9980
9981         if (!Printer) {
9982                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9983                         OUR_HANDLE(r->in.handle)));
9984                 return WERR_BADFID;
9985         }
9986
9987         /* if keyname == NULL, return error */
9988         if ( !r->in.key_name )
9989                 return WERR_INVALID_PARAM;
9990
9991         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9992                 return WERR_BADFID;
9993         }
9994
9995         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9996                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9997                         "printer properties change denied by handle\n"));
9998                 return WERR_ACCESS_DENIED;
9999         }
10000
10001         printer = lp_const_servicename(snum);
10002
10003         tmp_ctx = talloc_new(p->mem_ctx);
10004         if (!tmp_ctx) {
10005                 return WERR_NOMEM;
10006         }
10007
10008         status = winreg_printer_binding_handle(tmp_ctx,
10009                                                get_session_info_system(),
10010                                                p->msg_ctx,
10011                                                &b);
10012         if (!W_ERROR_IS_OK(status)) {
10013                 goto done;
10014         }
10015
10016         /* delete the key and all subkeys */
10017         status = winreg_delete_printer_key(tmp_ctx, b,
10018                                            printer,
10019                                            r->in.key_name);
10020         if (W_ERROR_IS_OK(status)) {
10021                 status = winreg_printer_update_changeid(tmp_ctx, b,
10022                                                         printer);
10023         }
10024
10025 done:
10026         talloc_free(tmp_ctx);
10027         return status;
10028 }
10029
10030 /****************************************************************
10031  _spoolss_EnumPrinterDataEx
10032 ****************************************************************/
10033
10034 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10035                                   struct spoolss_EnumPrinterDataEx *r)
10036 {
10037         uint32_t        count = 0;
10038         struct spoolss_PrinterEnumValues *info = NULL;
10039         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10040         int             snum;
10041         WERROR          result;
10042
10043         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10044
10045         *r->out.count = 0;
10046         *r->out.needed = 0;
10047         *r->out.info = NULL;
10048
10049         if (!Printer) {
10050                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10051                         OUR_HANDLE(r->in.handle)));
10052                 return WERR_BADFID;
10053         }
10054
10055         /*
10056          * first check for a keyname of NULL or "".  Win2k seems to send
10057          * this a lot and we should send back WERR_INVALID_PARAM
10058          * no need to spend time looking up the printer in this case.
10059          * --jerry
10060          */
10061
10062         if (!strlen(r->in.key_name)) {
10063                 result = WERR_INVALID_PARAM;
10064                 goto done;
10065         }
10066
10067         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10068                 return WERR_BADFID;
10069         }
10070
10071         /* now look for a match on the key name */
10072         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10073                                             get_session_info_system(),
10074                                             p->msg_ctx,
10075                                             lp_const_servicename(snum),
10076                                             r->in.key_name,
10077                                             &count,
10078                                             &info);
10079         if (!W_ERROR_IS_OK(result)) {
10080                 goto done;
10081         }
10082
10083 #if 0 /* FIXME - gd */
10084         /* housekeeping information in the reply */
10085
10086         /* Fix from Martin Zielinski <mz@seh.de> - ensure
10087          * the hand marshalled container size is a multiple
10088          * of 4 bytes for RPC alignment.
10089          */
10090
10091         if (needed % 4) {
10092                 needed += 4-(needed % 4);
10093         }
10094 #endif
10095         *r->out.count   = count;
10096         *r->out.info    = info;
10097
10098  done:
10099         if (!W_ERROR_IS_OK(result)) {
10100                 return result;
10101         }
10102
10103         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10104                                                spoolss_EnumPrinterDataEx,
10105                                                *r->out.info,
10106                                                *r->out.count);
10107         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10108         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10109
10110         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10111 }
10112
10113 /****************************************************************************
10114 ****************************************************************************/
10115
10116 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10117                                                  const char *servername,
10118                                                  const char *environment,
10119                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
10120 {
10121         WERROR werr;
10122         char *path = NULL;
10123
10124         werr = compose_spoolss_server_path(mem_ctx,
10125                                            servername,
10126                                            environment,
10127                                            SPOOLSS_PRTPROCS_PATH,
10128                                            &path);
10129         if (!W_ERROR_IS_OK(werr)) {
10130                 return werr;
10131         }
10132
10133         DEBUG(4,("print processor directory: [%s]\n", path));
10134
10135         r->directory_name = path;
10136
10137         return WERR_OK;
10138 }
10139
10140 /****************************************************************
10141  _spoolss_GetPrintProcessorDirectory
10142 ****************************************************************/
10143
10144 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10145                                            struct spoolss_GetPrintProcessorDirectory *r)
10146 {
10147         WERROR result;
10148         char *prnproc_share = NULL;
10149         bool prnproc_share_exists = false;
10150         int snum;
10151
10152         /* that's an [in out] buffer */
10153
10154         if (!r->in.buffer && (r->in.offered != 0)) {
10155                 result = WERR_INVALID_PARAM;
10156                 goto err_info_free;
10157         }
10158
10159         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10160                 r->in.level));
10161
10162         *r->out.needed = 0;
10163
10164         /* r->in.level is ignored */
10165
10166         /* We always should reply with a local print processor directory so that
10167          * users are not forced to have a [prnproc$] share on the Samba spoolss
10168          * server, if users decide to do so, lets announce it though - Guenther */
10169
10170         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10171         if (!prnproc_share) {
10172                 result = WERR_NOMEM;
10173                 goto err_info_free;
10174         }
10175         if (snum != -1) {
10176                 prnproc_share_exists = true;
10177         }
10178
10179         result = getprintprocessordirectory_level_1(p->mem_ctx,
10180                                                     prnproc_share_exists ? r->in.server : NULL,
10181                                                     r->in.environment,
10182                                                     &r->out.info->info1);
10183         if (!W_ERROR_IS_OK(result)) {
10184                 goto err_info_free;
10185         }
10186
10187         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10188                                                                                    r->out.info, r->in.level);
10189         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10190
10191         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10192
10193 err_info_free:
10194         TALLOC_FREE(r->out.info);
10195         return result;
10196 }
10197
10198 /*******************************************************************
10199  ********************************************************************/
10200
10201 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10202                                const char *dllname)
10203 {
10204         enum ndr_err_code ndr_err;
10205         struct spoolss_MonitorUi ui;
10206
10207         ui.dll_name = dllname;
10208
10209         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10210                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10211         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10212                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10213         }
10214         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10215 }
10216
10217 /*******************************************************************
10218  Streams the monitor UI DLL name in UNICODE
10219 *******************************************************************/
10220
10221 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10222                                struct security_token *token, DATA_BLOB *in,
10223                                DATA_BLOB *out, uint32_t *needed)
10224 {
10225         const char *dllname = "tcpmonui.dll";
10226
10227         *needed = (strlen(dllname)+1) * 2;
10228
10229         if (out->length < *needed) {
10230                 return WERR_INSUFFICIENT_BUFFER;
10231         }
10232
10233         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10234                 return WERR_NOMEM;
10235         }
10236
10237         return WERR_OK;
10238 }
10239
10240 /*******************************************************************
10241  ********************************************************************/
10242
10243 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10244                              struct spoolss_PortData1 *port1,
10245                              const DATA_BLOB *buf)
10246 {
10247         enum ndr_err_code ndr_err;
10248         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10249                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10250         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10251                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10252         }
10253         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10254 }
10255
10256 /*******************************************************************
10257  ********************************************************************/
10258
10259 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10260                              struct spoolss_PortData2 *port2,
10261                              const DATA_BLOB *buf)
10262 {
10263         enum ndr_err_code ndr_err;
10264         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10265                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10266         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10267                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10268         }
10269         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10270 }
10271
10272 /*******************************************************************
10273  Create a new TCP/IP port
10274 *******************************************************************/
10275
10276 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10277                              struct security_token *token, DATA_BLOB *in,
10278                              DATA_BLOB *out, uint32_t *needed)
10279 {
10280         struct spoolss_PortData1 port1;
10281         struct spoolss_PortData2 port2;
10282         char *device_uri = NULL;
10283         uint32_t version;
10284
10285         const char *portname;
10286         const char *hostaddress;
10287         const char *queue;
10288         uint32_t port_number;
10289         uint32_t protocol;
10290
10291         /* peek for spoolss_PortData version */
10292
10293         if (!in || (in->length < (128 + 4))) {
10294                 return WERR_GENERAL_FAILURE;
10295         }
10296
10297         version = IVAL(in->data, 128);
10298
10299         switch (version) {
10300                 case 1:
10301                         ZERO_STRUCT(port1);
10302
10303                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10304                                 return WERR_NOMEM;
10305                         }
10306
10307                         portname        = port1.portname;
10308                         hostaddress     = port1.hostaddress;
10309                         queue           = port1.queue;
10310                         protocol        = port1.protocol;
10311                         port_number     = port1.port_number;
10312
10313                         break;
10314                 case 2:
10315                         ZERO_STRUCT(port2);
10316
10317                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10318                                 return WERR_NOMEM;
10319                         }
10320
10321                         portname        = port2.portname;
10322                         hostaddress     = port2.hostaddress;
10323                         queue           = port2.queue;
10324                         protocol        = port2.protocol;
10325                         port_number     = port2.port_number;
10326
10327                         break;
10328                 default:
10329                         DEBUG(1,("xcvtcp_addport: "
10330                                 "unknown version of port_data: %d\n", version));
10331                         return WERR_UNKNOWN_PORT;
10332         }
10333
10334         /* create the device URI and call the add_port_hook() */
10335
10336         switch (protocol) {
10337         case PROTOCOL_RAWTCP_TYPE:
10338                 device_uri = talloc_asprintf(mem_ctx,
10339                                 "socket://%s:%d/", hostaddress,
10340                                 port_number);
10341                 break;
10342
10343         case PROTOCOL_LPR_TYPE:
10344                 device_uri = talloc_asprintf(mem_ctx,
10345                         "lpr://%s/%s", hostaddress, queue );
10346                 break;
10347
10348         default:
10349                 return WERR_UNKNOWN_PORT;
10350         }
10351
10352         if (!device_uri) {
10353                 return WERR_NOMEM;
10354         }
10355
10356         return add_port_hook(mem_ctx, token, portname, device_uri);
10357 }
10358
10359 /*******************************************************************
10360 *******************************************************************/
10361
10362 struct xcv_api_table xcvtcp_cmds[] = {
10363         { "MonitorUI",  xcvtcp_monitorui },
10364         { "AddPort",    xcvtcp_addport},
10365         { NULL,         NULL }
10366 };
10367
10368 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10369                                      struct security_token *token, const char *command,
10370                                      DATA_BLOB *inbuf,
10371                                      DATA_BLOB *outbuf,
10372                                      uint32_t *needed )
10373 {
10374         int i;
10375
10376         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10377
10378         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10379                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10380                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10381         }
10382
10383         return WERR_BADFUNC;
10384 }
10385
10386 /*******************************************************************
10387 *******************************************************************/
10388 #if 0   /* don't support management using the "Local Port" monitor */
10389
10390 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10391                                  struct security_token *token, DATA_BLOB *in,
10392                                  DATA_BLOB *out, uint32_t *needed)
10393 {
10394         const char *dllname = "localui.dll";
10395
10396         *needed = (strlen(dllname)+1) * 2;
10397
10398         if (out->length < *needed) {
10399                 return WERR_INSUFFICIENT_BUFFER;
10400         }
10401
10402         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10403                 return WERR_NOMEM;
10404         }
10405
10406         return WERR_OK;
10407 }
10408
10409 /*******************************************************************
10410 *******************************************************************/
10411
10412 struct xcv_api_table xcvlocal_cmds[] = {
10413         { "MonitorUI",  xcvlocal_monitorui },
10414         { NULL,         NULL }
10415 };
10416 #else
10417 struct xcv_api_table xcvlocal_cmds[] = {
10418         { NULL,         NULL }
10419 };
10420 #endif
10421
10422
10423
10424 /*******************************************************************
10425 *******************************************************************/
10426
10427 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10428                                        struct security_token *token, const char *command,
10429                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10430                                        uint32_t *needed)
10431 {
10432         int i;
10433
10434         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10435
10436         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10437                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10438                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10439         }
10440         return WERR_BADFUNC;
10441 }
10442
10443 /****************************************************************
10444  _spoolss_XcvData
10445 ****************************************************************/
10446
10447 WERROR _spoolss_XcvData(struct pipes_struct *p,
10448                         struct spoolss_XcvData *r)
10449 {
10450         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10451         DATA_BLOB out_data = data_blob_null;
10452         WERROR werror;
10453
10454         if (!Printer) {
10455                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10456                         OUR_HANDLE(r->in.handle)));
10457                 return WERR_BADFID;
10458         }
10459
10460         /* Has to be a handle to the TCP/IP port monitor */
10461
10462         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10463                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10464                 return WERR_BADFID;
10465         }
10466
10467         /* requires administrative access to the server */
10468
10469         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10470                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10471                 return WERR_ACCESS_DENIED;
10472         }
10473
10474         /* Allocate the outgoing buffer */
10475
10476         if (r->in.out_data_size) {
10477                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10478                 if (out_data.data == NULL) {
10479                         return WERR_NOMEM;
10480                 }
10481         }
10482
10483         switch ( Printer->printer_type ) {
10484         case SPLHND_PORTMON_TCP:
10485                 werror = process_xcvtcp_command(p->mem_ctx,
10486                                                 p->session_info->security_token,
10487                                                 r->in.function_name,
10488                                                 &r->in.in_data, &out_data,
10489                                                 r->out.needed);
10490                 break;
10491         case SPLHND_PORTMON_LOCAL:
10492                 werror = process_xcvlocal_command(p->mem_ctx,
10493                                                   p->session_info->security_token,
10494                                                   r->in.function_name,
10495                                                   &r->in.in_data, &out_data,
10496                                                   r->out.needed);
10497                 break;
10498         default:
10499                 werror = WERR_INVALID_PRINT_MONITOR;
10500         }
10501
10502         if (!W_ERROR_IS_OK(werror)) {
10503                 return werror;
10504         }
10505
10506         *r->out.status_code = 0;
10507
10508         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10509                 memcpy(r->out.out_data, out_data.data,
10510                         MIN(r->in.out_data_size, out_data.length));
10511         }
10512
10513         return WERR_OK;
10514 }
10515
10516 /****************************************************************
10517  _spoolss_AddPrintProcessor
10518 ****************************************************************/
10519
10520 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10521                                   struct spoolss_AddPrintProcessor *r)
10522 {
10523         /* for now, just indicate success and ignore the add.  We'll
10524            automatically set the winprint processor for printer
10525            entries later.  Used to debug the LexMark Optra S 1855 PCL
10526            driver --jerry */
10527
10528         return WERR_OK;
10529 }
10530
10531 /****************************************************************
10532  _spoolss_AddPort
10533 ****************************************************************/
10534
10535 WERROR _spoolss_AddPort(struct pipes_struct *p,
10536                         struct spoolss_AddPort *r)
10537 {
10538         /* do what w2k3 does */
10539
10540         return WERR_NOT_SUPPORTED;
10541 }
10542
10543 /****************************************************************
10544  _spoolss_GetPrinterDriver
10545 ****************************************************************/
10546
10547 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10548                                  struct spoolss_GetPrinterDriver *r)
10549 {
10550         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10551         return WERR_NOT_SUPPORTED;
10552 }
10553
10554 /****************************************************************
10555  _spoolss_ReadPrinter
10556 ****************************************************************/
10557
10558 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10559                             struct spoolss_ReadPrinter *r)
10560 {
10561         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10562         return WERR_NOT_SUPPORTED;
10563 }
10564
10565 /****************************************************************
10566  _spoolss_WaitForPrinterChange
10567 ****************************************************************/
10568
10569 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10570                                      struct spoolss_WaitForPrinterChange *r)
10571 {
10572         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10573         return WERR_NOT_SUPPORTED;
10574 }
10575
10576 /****************************************************************
10577  _spoolss_ConfigurePort
10578 ****************************************************************/
10579
10580 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10581                               struct spoolss_ConfigurePort *r)
10582 {
10583         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10584         return WERR_NOT_SUPPORTED;
10585 }
10586
10587 /****************************************************************
10588  _spoolss_DeletePort
10589 ****************************************************************/
10590
10591 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10592                            struct spoolss_DeletePort *r)
10593 {
10594         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10595         return WERR_NOT_SUPPORTED;
10596 }
10597
10598 /****************************************************************
10599  _spoolss_CreatePrinterIC
10600 ****************************************************************/
10601
10602 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10603                                 struct spoolss_CreatePrinterIC *r)
10604 {
10605         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10606         return WERR_NOT_SUPPORTED;
10607 }
10608
10609 /****************************************************************
10610  _spoolss_PlayGDIScriptOnPrinterIC
10611 ****************************************************************/
10612
10613 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10614                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10615 {
10616         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10617         return WERR_NOT_SUPPORTED;
10618 }
10619
10620 /****************************************************************
10621  _spoolss_DeletePrinterIC
10622 ****************************************************************/
10623
10624 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10625                                 struct spoolss_DeletePrinterIC *r)
10626 {
10627         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10628         return WERR_NOT_SUPPORTED;
10629 }
10630
10631 /****************************************************************
10632  _spoolss_AddPrinterConnection
10633 ****************************************************************/
10634
10635 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10636                                      struct spoolss_AddPrinterConnection *r)
10637 {
10638         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10639         return WERR_NOT_SUPPORTED;
10640 }
10641
10642 /****************************************************************
10643  _spoolss_DeletePrinterConnection
10644 ****************************************************************/
10645
10646 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10647                                         struct spoolss_DeletePrinterConnection *r)
10648 {
10649         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10650         return WERR_NOT_SUPPORTED;
10651 }
10652
10653 /****************************************************************
10654  _spoolss_PrinterMessageBox
10655 ****************************************************************/
10656
10657 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10658                                   struct spoolss_PrinterMessageBox *r)
10659 {
10660         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10661         return WERR_NOT_SUPPORTED;
10662 }
10663
10664 /****************************************************************
10665  _spoolss_AddMonitor
10666 ****************************************************************/
10667
10668 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10669                            struct spoolss_AddMonitor *r)
10670 {
10671         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10672         return WERR_NOT_SUPPORTED;
10673 }
10674
10675 /****************************************************************
10676  _spoolss_DeleteMonitor
10677 ****************************************************************/
10678
10679 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10680                               struct spoolss_DeleteMonitor *r)
10681 {
10682         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10683         return WERR_NOT_SUPPORTED;
10684 }
10685
10686 /****************************************************************
10687  _spoolss_DeletePrintProcessor
10688 ****************************************************************/
10689
10690 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10691                                      struct spoolss_DeletePrintProcessor *r)
10692 {
10693         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10694         return WERR_NOT_SUPPORTED;
10695 }
10696
10697 /****************************************************************
10698  _spoolss_AddPrintProvidor
10699 ****************************************************************/
10700
10701 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10702                                  struct spoolss_AddPrintProvidor *r)
10703 {
10704         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10705         return WERR_NOT_SUPPORTED;
10706 }
10707
10708 /****************************************************************
10709  _spoolss_DeletePrintProvidor
10710 ****************************************************************/
10711
10712 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10713                                     struct spoolss_DeletePrintProvidor *r)
10714 {
10715         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10716         return WERR_NOT_SUPPORTED;
10717 }
10718
10719 /****************************************************************
10720  _spoolss_FindFirstPrinterChangeNotification
10721 ****************************************************************/
10722
10723 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10724                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10725 {
10726         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10727         return WERR_NOT_SUPPORTED;
10728 }
10729
10730 /****************************************************************
10731  _spoolss_FindNextPrinterChangeNotification
10732 ****************************************************************/
10733
10734 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10735                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10736 {
10737         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10738         return WERR_NOT_SUPPORTED;
10739 }
10740
10741 /****************************************************************
10742  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10743 ****************************************************************/
10744
10745 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10746                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10747 {
10748         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10749         return WERR_NOT_SUPPORTED;
10750 }
10751
10752 /****************************************************************
10753  _spoolss_ReplyOpenPrinter
10754 ****************************************************************/
10755
10756 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10757                                  struct spoolss_ReplyOpenPrinter *r)
10758 {
10759         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10760         return WERR_NOT_SUPPORTED;
10761 }
10762
10763 /****************************************************************
10764  _spoolss_RouterReplyPrinter
10765 ****************************************************************/
10766
10767 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10768                                    struct spoolss_RouterReplyPrinter *r)
10769 {
10770         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10771         return WERR_NOT_SUPPORTED;
10772 }
10773
10774 /****************************************************************
10775  _spoolss_ReplyClosePrinter
10776 ****************************************************************/
10777
10778 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10779                                   struct spoolss_ReplyClosePrinter *r)
10780 {
10781         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10782         return WERR_NOT_SUPPORTED;
10783 }
10784
10785 /****************************************************************
10786  _spoolss_AddPortEx
10787 ****************************************************************/
10788
10789 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10790                           struct spoolss_AddPortEx *r)
10791 {
10792         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10793         return WERR_NOT_SUPPORTED;
10794 }
10795
10796 /****************************************************************
10797  _spoolss_RouterFindFirstPrinterChangeNotification
10798 ****************************************************************/
10799
10800 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10801                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10802 {
10803         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10804         return WERR_NOT_SUPPORTED;
10805 }
10806
10807 /****************************************************************
10808  _spoolss_SpoolerInit
10809 ****************************************************************/
10810
10811 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10812                             struct spoolss_SpoolerInit *r)
10813 {
10814         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10815         return WERR_NOT_SUPPORTED;
10816 }
10817
10818 /****************************************************************
10819  _spoolss_ResetPrinterEx
10820 ****************************************************************/
10821
10822 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10823                                struct spoolss_ResetPrinterEx *r)
10824 {
10825         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10826         return WERR_NOT_SUPPORTED;
10827 }
10828
10829 /****************************************************************
10830  _spoolss_RouterReplyPrinterEx
10831 ****************************************************************/
10832
10833 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10834                                      struct spoolss_RouterReplyPrinterEx *r)
10835 {
10836         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10837         return WERR_NOT_SUPPORTED;
10838 }
10839
10840 /****************************************************************
10841  _spoolss_44
10842 ****************************************************************/
10843
10844 WERROR _spoolss_44(struct pipes_struct *p,
10845                    struct spoolss_44 *r)
10846 {
10847         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10848         return WERR_NOT_SUPPORTED;
10849 }
10850
10851 /****************************************************************
10852  _spoolss_SetPort
10853 ****************************************************************/
10854
10855 WERROR _spoolss_SetPort(struct pipes_struct *p,
10856                         struct spoolss_SetPort *r)
10857 {
10858         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10859         return WERR_NOT_SUPPORTED;
10860 }
10861
10862 /****************************************************************
10863  _spoolss_4a
10864 ****************************************************************/
10865
10866 WERROR _spoolss_4a(struct pipes_struct *p,
10867                    struct spoolss_4a *r)
10868 {
10869         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10870         return WERR_NOT_SUPPORTED;
10871 }
10872
10873 /****************************************************************
10874  _spoolss_4b
10875 ****************************************************************/
10876
10877 WERROR _spoolss_4b(struct pipes_struct *p,
10878                    struct spoolss_4b *r)
10879 {
10880         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10881         return WERR_NOT_SUPPORTED;
10882 }
10883
10884 /****************************************************************
10885  _spoolss_4c
10886 ****************************************************************/
10887
10888 WERROR _spoolss_4c(struct pipes_struct *p,
10889                    struct spoolss_4c *r)
10890 {
10891         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10892         return WERR_NOT_SUPPORTED;
10893 }
10894
10895 /****************************************************************
10896  _spoolss_53
10897 ****************************************************************/
10898
10899 WERROR _spoolss_53(struct pipes_struct *p,
10900                    struct spoolss_53 *r)
10901 {
10902         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10903         return WERR_NOT_SUPPORTED;
10904 }
10905
10906 /****************************************************************
10907  _spoolss_AddPerMachineConnection
10908 ****************************************************************/
10909
10910 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10911                                         struct spoolss_AddPerMachineConnection *r)
10912 {
10913         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10914         return WERR_NOT_SUPPORTED;
10915 }
10916
10917 /****************************************************************
10918  _spoolss_DeletePerMachineConnection
10919 ****************************************************************/
10920
10921 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10922                                            struct spoolss_DeletePerMachineConnection *r)
10923 {
10924         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10925         return WERR_NOT_SUPPORTED;
10926 }
10927
10928 /****************************************************************
10929  _spoolss_EnumPerMachineConnections
10930 ****************************************************************/
10931
10932 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10933                                           struct spoolss_EnumPerMachineConnections *r)
10934 {
10935         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10936         return WERR_NOT_SUPPORTED;
10937 }
10938
10939 /****************************************************************
10940  _spoolss_5a
10941 ****************************************************************/
10942
10943 WERROR _spoolss_5a(struct pipes_struct *p,
10944                    struct spoolss_5a *r)
10945 {
10946         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10947         return WERR_NOT_SUPPORTED;
10948 }
10949
10950 /****************************************************************
10951  _spoolss_5b
10952 ****************************************************************/
10953
10954 WERROR _spoolss_5b(struct pipes_struct *p,
10955                    struct spoolss_5b *r)
10956 {
10957         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10958         return WERR_NOT_SUPPORTED;
10959 }
10960
10961 /****************************************************************
10962  _spoolss_5c
10963 ****************************************************************/
10964
10965 WERROR _spoolss_5c(struct pipes_struct *p,
10966                    struct spoolss_5c *r)
10967 {
10968         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10969         return WERR_NOT_SUPPORTED;
10970 }
10971
10972 /****************************************************************
10973  _spoolss_5d
10974 ****************************************************************/
10975
10976 WERROR _spoolss_5d(struct pipes_struct *p,
10977                    struct spoolss_5d *r)
10978 {
10979         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10980         return WERR_NOT_SUPPORTED;
10981 }
10982
10983 /****************************************************************
10984  _spoolss_5e
10985 ****************************************************************/
10986
10987 WERROR _spoolss_5e(struct pipes_struct *p,
10988                    struct spoolss_5e *r)
10989 {
10990         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10991         return WERR_NOT_SUPPORTED;
10992 }
10993
10994 /****************************************************************
10995  _spoolss_5f
10996 ****************************************************************/
10997
10998 WERROR _spoolss_5f(struct pipes_struct *p,
10999                    struct spoolss_5f *r)
11000 {
11001         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11002         return WERR_NOT_SUPPORTED;
11003 }
11004
11005 /****************************************************************
11006  _spoolss_60
11007 ****************************************************************/
11008
11009 WERROR _spoolss_60(struct pipes_struct *p,
11010                    struct spoolss_60 *r)
11011 {
11012         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11013         return WERR_NOT_SUPPORTED;
11014 }
11015
11016 /****************************************************************
11017  _spoolss_RpcSendRecvBidiData
11018 ****************************************************************/
11019
11020 WERROR _spoolss_RpcSendRecvBidiData(struct pipes_struct *p,
11021                                     struct spoolss_RpcSendRecvBidiData *r)
11022 {
11023         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11024         return WERR_NOT_SUPPORTED;
11025 }
11026
11027 /****************************************************************
11028  _spoolss_62
11029 ****************************************************************/
11030
11031 WERROR _spoolss_62(struct pipes_struct *p,
11032                    struct spoolss_62 *r)
11033 {
11034         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11035         return WERR_NOT_SUPPORTED;
11036 }
11037
11038 /****************************************************************
11039  _spoolss_63
11040 ****************************************************************/
11041
11042 WERROR _spoolss_63(struct pipes_struct *p,
11043                    struct spoolss_63 *r)
11044 {
11045         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11046         return WERR_NOT_SUPPORTED;
11047 }
11048
11049 /****************************************************************
11050  _spoolss_64
11051 ****************************************************************/
11052
11053 WERROR _spoolss_64(struct pipes_struct *p,
11054                    struct spoolss_64 *r)
11055 {
11056         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11057         return WERR_NOT_SUPPORTED;
11058 }
11059
11060 /****************************************************************
11061  _spoolss_65
11062 ****************************************************************/
11063
11064 WERROR _spoolss_65(struct pipes_struct *p,
11065                    struct spoolss_65 *r)
11066 {
11067         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11068         return WERR_NOT_SUPPORTED;
11069 }
11070
11071 /****************************************************************
11072  _spoolss_GetCorePrinterDrivers
11073 ****************************************************************/
11074
11075 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11076                                       struct spoolss_GetCorePrinterDrivers *r)
11077 {
11078         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11079         return WERR_NOT_SUPPORTED;
11080 }
11081
11082 /****************************************************************
11083  _spoolss_67
11084 ****************************************************************/
11085
11086 WERROR _spoolss_67(struct pipes_struct *p,
11087                    struct spoolss_67 *r)
11088 {
11089         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11090         return WERR_NOT_SUPPORTED;
11091 }
11092
11093 /****************************************************************
11094  _spoolss_GetPrinterDriverPackagePath
11095 ****************************************************************/
11096
11097 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11098                                             struct spoolss_GetPrinterDriverPackagePath *r)
11099 {
11100         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11101         return WERR_NOT_SUPPORTED;
11102 }
11103
11104 /****************************************************************
11105  _spoolss_69
11106 ****************************************************************/
11107
11108 WERROR _spoolss_69(struct pipes_struct *p,
11109                    struct spoolss_69 *r)
11110 {
11111         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11112         return WERR_NOT_SUPPORTED;
11113 }
11114
11115 /****************************************************************
11116  _spoolss_6a
11117 ****************************************************************/
11118
11119 WERROR _spoolss_6a(struct pipes_struct *p,
11120                    struct spoolss_6a *r)
11121 {
11122         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11123         return WERR_NOT_SUPPORTED;
11124 }
11125
11126 /****************************************************************
11127  _spoolss_6b
11128 ****************************************************************/
11129
11130 WERROR _spoolss_6b(struct pipes_struct *p,
11131                    struct spoolss_6b *r)
11132 {
11133         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11134         return WERR_NOT_SUPPORTED;
11135 }
11136
11137 /****************************************************************
11138  _spoolss_6c
11139 ****************************************************************/
11140
11141 WERROR _spoolss_6c(struct pipes_struct *p,
11142                    struct spoolss_6c *r)
11143 {
11144         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11145         return WERR_NOT_SUPPORTED;
11146 }
11147
11148 /****************************************************************
11149  _spoolss_6d
11150 ****************************************************************/
11151
11152 WERROR _spoolss_6d(struct pipes_struct *p,
11153                    struct spoolss_6d *r)
11154 {
11155         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11156         return WERR_NOT_SUPPORTED;
11157 }
11158
11159 /****************************************************************
11160  _spoolss_RpcGetJobNamedPropertyValue
11161 ****************************************************************/
11162
11163 WERROR _spoolss_RpcGetJobNamedPropertyValue(struct pipes_struct *p,
11164                                             struct spoolss_RpcGetJobNamedPropertyValue *r)
11165 {
11166         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11167         return WERR_NOT_SUPPORTED;
11168 }
11169
11170 /****************************************************************
11171  _spoolss_RpcSetJobNamedProperty
11172 ****************************************************************/
11173
11174 WERROR _spoolss_RpcSetJobNamedProperty(struct pipes_struct *p,
11175                                        struct spoolss_RpcSetJobNamedProperty *r)
11176 {
11177         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11178         return WERR_NOT_SUPPORTED;
11179 }
11180
11181 /****************************************************************
11182  _spoolss_RpcDeleteJobNamedProperty
11183 ****************************************************************/
11184
11185 WERROR _spoolss_RpcDeleteJobNamedProperty(struct pipes_struct *p,
11186                                           struct spoolss_RpcDeleteJobNamedProperty *r)
11187 {
11188         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11189         return WERR_NOT_SUPPORTED;
11190 }
11191
11192 /****************************************************************
11193  _spoolss_RpcEnumJobNamedProperties
11194 ****************************************************************/
11195
11196 WERROR _spoolss_RpcEnumJobNamedProperties(struct pipes_struct *p,
11197                                           struct spoolss_RpcEnumJobNamedProperties *r)
11198 {
11199         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11200         return WERR_NOT_SUPPORTED;
11201 }