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