s3-spoolss: do not use rpc_pipe_np_smb_conn()
[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_cmd(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_print_ok(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 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
850         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
851         if (!_data->data.sd.sd) { \
852                 _data->data.sd.sd_size = 0; \
853         } \
854         _data->data.sd.sd_size = \
855                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
856
857 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
858                                    struct tm *t,
859                                    const char **pp,
860                                    uint32_t *plen)
861 {
862         struct spoolss_Time st;
863         uint32_t len = 16;
864         char *p;
865
866         if (!init_systemtime(&st, t)) {
867                 return;
868         }
869
870         p = talloc_array(mem_ctx, char, len);
871         if (!p) {
872                 return;
873         }
874
875         /*
876          * Systemtime must be linearized as a set of UINT16's.
877          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
878          */
879
880         SSVAL(p, 0, st.year);
881         SSVAL(p, 2, st.month);
882         SSVAL(p, 4, st.day_of_week);
883         SSVAL(p, 6, st.day);
884         SSVAL(p, 8, st.hour);
885         SSVAL(p, 10, st.minute);
886         SSVAL(p, 12, st.second);
887         SSVAL(p, 14, st.millisecond);
888
889         *pp = p;
890         *plen = len;
891 }
892
893 /* Convert a notification message to a struct spoolss_Notify */
894
895 static void notify_one_value(struct spoolss_notify_msg *msg,
896                              struct spoolss_Notify *data,
897                              TALLOC_CTX *mem_ctx)
898 {
899         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
900 }
901
902 static void notify_string(struct spoolss_notify_msg *msg,
903                           struct spoolss_Notify *data,
904                           TALLOC_CTX *mem_ctx)
905 {
906         /* The length of the message includes the trailing \0 */
907
908         data->data.string.size = msg->len * 2;
909         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
910         if (!data->data.string.string) {
911                 data->data.string.size = 0;
912                 return;
913         }
914 }
915
916 static void notify_system_time(struct spoolss_notify_msg *msg,
917                                struct spoolss_Notify *data,
918                                TALLOC_CTX *mem_ctx)
919 {
920         data->data.string.string = NULL;
921         data->data.string.size = 0;
922
923         if (msg->len != sizeof(time_t)) {
924                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
925                           msg->len));
926                 return;
927         }
928
929         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
930                                &data->data.string.string,
931                                &data->data.string.size);
932 }
933
934 struct notify2_message_table {
935         const char *name;
936         void (*fn)(struct spoolss_notify_msg *msg,
937                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
938 };
939
940 static struct notify2_message_table printer_notify_table[] = {
941         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
942         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
943         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
944         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
945         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
946         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
947         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
948         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
949         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
950         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
951         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
952         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
953         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
954         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
955         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
956         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
957         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
958         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
959         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
960 };
961
962 static struct notify2_message_table job_notify_table[] = {
963         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
964         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
965         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
966         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
967         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
968         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
969         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
970         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
971         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
972         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
973         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
974         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
975         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
976         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
977         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
978         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
979         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
980         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
981         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
982         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
983         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
984         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
985         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
986         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
987 };
988
989
990 /***********************************************************************
991  Allocate talloc context for container object
992  **********************************************************************/
993
994 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
995 {
996         if ( !ctr )
997                 return;
998
999         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1000
1001         return;
1002 }
1003
1004 /***********************************************************************
1005  release all allocated memory and zero out structure
1006  **********************************************************************/
1007
1008 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1009 {
1010         if ( !ctr )
1011                 return;
1012
1013         if ( ctr->ctx )
1014                 talloc_destroy(ctr->ctx);
1015
1016         ZERO_STRUCTP(ctr);
1017
1018         return;
1019 }
1020
1021 /***********************************************************************
1022  **********************************************************************/
1023
1024 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1025 {
1026         if ( !ctr )
1027                 return NULL;
1028
1029         return ctr->ctx;
1030 }
1031
1032 /***********************************************************************
1033  **********************************************************************/
1034
1035 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1036 {
1037         if ( !ctr || !ctr->msg_groups )
1038                 return NULL;
1039
1040         if ( idx >= ctr->num_groups )
1041                 return NULL;
1042
1043         return &ctr->msg_groups[idx];
1044
1045 }
1046
1047 /***********************************************************************
1048  How many groups of change messages do we have ?
1049  **********************************************************************/
1050
1051 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1052 {
1053         if ( !ctr )
1054                 return 0;
1055
1056         return ctr->num_groups;
1057 }
1058
1059 /***********************************************************************
1060  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1061  **********************************************************************/
1062
1063 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1064 {
1065         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1066         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1067         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1068         int                             i, new_slot;
1069
1070         if ( !ctr || !msg )
1071                 return 0;
1072
1073         /* loop over all groups looking for a matching printer name */
1074
1075         for ( i=0; i<ctr->num_groups; i++ ) {
1076                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1077                         break;
1078         }
1079
1080         /* add a new group? */
1081
1082         if ( i == ctr->num_groups ) {
1083                 ctr->num_groups++;
1084
1085                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1086                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1087                         return 0;
1088                 }
1089                 ctr->msg_groups = groups;
1090
1091                 /* clear the new entry and set the printer name */
1092
1093                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1094                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1095         }
1096
1097         /* add the change messages; 'i' is the correct index now regardless */
1098
1099         msg_grp = &ctr->msg_groups[i];
1100
1101         msg_grp->num_msgs++;
1102
1103         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1104                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1105                 return 0;
1106         }
1107         msg_grp->msgs = msg_list;
1108
1109         new_slot = msg_grp->num_msgs-1;
1110         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1111
1112         /* need to allocate own copy of data */
1113
1114         if ( msg->len != 0 )
1115                 msg_grp->msgs[new_slot].notify.data = (char *)
1116                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1117
1118         return ctr->num_groups;
1119 }
1120
1121 static void construct_info_data(struct spoolss_Notify *info_data,
1122                                 enum spoolss_NotifyType type,
1123                                 uint16_t field, int id);
1124
1125 /***********************************************************************
1126  Send a change notication message on all handles which have a call
1127  back registered
1128  **********************************************************************/
1129
1130 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1131                                   struct printer_handle *prn_hnd,
1132                                   SPOOLSS_NOTIFY_MSG *messages,
1133                                   uint32_t num_msgs,
1134                                   struct spoolss_Notify **_notifies,
1135                                   int *_count)
1136 {
1137         struct spoolss_Notify *notifies;
1138         SPOOLSS_NOTIFY_MSG *msg;
1139         int count = 0;
1140         uint32_t id;
1141         int i;
1142
1143         notifies = talloc_zero_array(mem_ctx,
1144                                      struct spoolss_Notify, num_msgs);
1145         if (!notifies) {
1146                 return ENOMEM;
1147         }
1148
1149         for (i = 0; i < num_msgs; i++) {
1150
1151                 msg = &messages[i];
1152
1153                 /* Are we monitoring this event? */
1154
1155                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1156                         continue;
1157                 }
1158
1159                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1160                            "for printer [%s]\n",
1161                            msg->type, msg->field, prn_hnd->sharename));
1162
1163                 /*
1164                  * if the is a printer notification handle and not a job
1165                  * notification type, then set the id to 0.
1166                  * Otherwise just use what was specified in the message.
1167                  *
1168                  * When registering change notification on a print server
1169                  * handle we always need to send back the id (snum) matching
1170                  * the printer for which the change took place.
1171                  * For change notify registered on a printer handle,
1172                  * this does not matter and the id should be 0.
1173                  *
1174                  * --jerry
1175                  */
1176
1177                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1178                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1179                         id = 0;
1180                 } else {
1181                         id = msg->id;
1182                 }
1183
1184                 /* Convert unix jobid to smb jobid */
1185
1186                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1187                         id = sysjob_to_jobid(msg->id);
1188
1189                         if (id == -1) {
1190                                 DEBUG(3, ("no such unix jobid %d\n",
1191                                           msg->id));
1192                                 continue;
1193                         }
1194                 }
1195
1196                 construct_info_data(&notifies[count],
1197                                     msg->type, msg->field, id);
1198
1199                 switch(msg->type) {
1200                 case PRINTER_NOTIFY_TYPE:
1201                         if (printer_notify_table[msg->field].fn) {
1202                                 printer_notify_table[msg->field].fn(msg,
1203                                                 &notifies[count], mem_ctx);
1204                         }
1205                         break;
1206
1207                 case JOB_NOTIFY_TYPE:
1208                         if (job_notify_table[msg->field].fn) {
1209                                 job_notify_table[msg->field].fn(msg,
1210                                                 &notifies[count], mem_ctx);
1211                         }
1212                         break;
1213
1214                 default:
1215                         DEBUG(5, ("Unknown notification type %d\n",
1216                                   msg->type));
1217                         continue;
1218                 }
1219
1220                 count++;
1221         }
1222
1223         *_notifies = notifies;
1224         *_count = count;
1225
1226         return 0;
1227 }
1228
1229 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1230                                 struct printer_handle *prn_hnd,
1231                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1232 {
1233         struct spoolss_Notify *notifies;
1234         int count = 0;
1235         union spoolss_ReplyPrinterInfo info;
1236         struct spoolss_NotifyInfo info0;
1237         uint32_t reply_result;
1238         NTSTATUS status;
1239         WERROR werr;
1240         int ret;
1241
1242         /* Is there notification on this handle? */
1243         if (prn_hnd->notify.cli_chan == NULL ||
1244             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1245             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1246             prn_hnd->notify.cli_chan->active_connections == 0) {
1247                 return 0;
1248         }
1249
1250         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1251                    prn_hnd->servername, prn_hnd->sharename));
1252
1253         /* For this printer? Print servers always receive notifications. */
1254         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1255             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1256                 return 0;
1257         }
1258
1259         DEBUG(10,("Our printer\n"));
1260
1261         /* build the array of change notifications */
1262         ret = build_notify2_messages(mem_ctx, prn_hnd,
1263                                      msg_group->msgs,
1264                                      msg_group->num_msgs,
1265                                      &notifies, &count);
1266         if (ret) {
1267                 return ret;
1268         }
1269
1270         info0.version   = 0x2;
1271         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1272         info0.count     = count;
1273         info0.notifies  = notifies;
1274
1275         info.info0 = &info0;
1276
1277         status = dcerpc_spoolss_RouterReplyPrinterEx(
1278                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1279                                 mem_ctx,
1280                                 &prn_hnd->notify.cli_hnd,
1281                                 prn_hnd->notify.change, /* color */
1282                                 prn_hnd->notify.flags,
1283                                 &reply_result,
1284                                 0, /* reply_type, must be 0 */
1285                                 info, &werr);
1286         if (!NT_STATUS_IS_OK(status)) {
1287                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1288                           "failed: %s\n",
1289                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1290                           nt_errstr(status)));
1291                 werr = ntstatus_to_werror(status);
1292         } else if (!W_ERROR_IS_OK(werr)) {
1293                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1294                           "failed: %s\n",
1295                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1296                           win_errstr(werr)));
1297         }
1298         switch (reply_result) {
1299         case 0:
1300                 break;
1301         case PRINTER_NOTIFY_INFO_DISCARDED:
1302         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1303         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1304                 break;
1305         default:
1306                 break;
1307         }
1308
1309         return 0;
1310 }
1311
1312 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1313 {
1314         struct printer_handle    *p;
1315         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1316         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1317         int ret;
1318
1319         if ( !msg_group ) {
1320                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1321                 return;
1322         }
1323
1324         if (!msg_group->msgs) {
1325                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1326                 return;
1327         }
1328
1329         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1330
1331         /* loop over all printers */
1332
1333         for (p = printers_list; p; p = p->next) {
1334                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1335                 if (ret) {
1336                         goto done;
1337                 }
1338         }
1339
1340 done:
1341         DEBUG(8,("send_notify2_changes: Exit...\n"));
1342         return;
1343 }
1344
1345 /***********************************************************************
1346  **********************************************************************/
1347
1348 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1349 {
1350
1351         uint32_t tv_sec, tv_usec;
1352         size_t offset = 0;
1353
1354         /* Unpack message */
1355
1356         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1357                              msg->printer);
1358
1359         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1360                                 &tv_sec, &tv_usec,
1361                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1362
1363         if (msg->len == 0)
1364                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1365                            &msg->notify.value[0], &msg->notify.value[1]);
1366         else
1367                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1368                            &msg->len, &msg->notify.data);
1369
1370         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1371                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1372
1373         tv->tv_sec = tv_sec;
1374         tv->tv_usec = tv_usec;
1375
1376         if (msg->len == 0)
1377                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1378                           msg->notify.value[1]));
1379         else
1380                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1381
1382         return true;
1383 }
1384
1385 /********************************************************************
1386  Receive a notify2 message list
1387  ********************************************************************/
1388
1389 static void receive_notify2_message_list(struct messaging_context *msg,
1390                                          void *private_data,
1391                                          uint32_t msg_type,
1392                                          struct server_id server_id,
1393                                          DATA_BLOB *data)
1394 {
1395         size_t                  msg_count, i;
1396         char                    *buf = (char *)data->data;
1397         char                    *msg_ptr;
1398         size_t                  msg_len;
1399         SPOOLSS_NOTIFY_MSG      notify;
1400         SPOOLSS_NOTIFY_MSG_CTR  messages;
1401         int                     num_groups;
1402
1403         if (data->length < 4) {
1404                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1405                 return;
1406         }
1407
1408         msg_count = IVAL(buf, 0);
1409         msg_ptr = buf + 4;
1410
1411         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1412
1413         if (msg_count == 0) {
1414                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1415                 return;
1416         }
1417
1418         /* initialize the container */
1419
1420         ZERO_STRUCT( messages );
1421         notify_msg_ctr_init( &messages );
1422
1423         /*
1424          * build message groups for each printer identified
1425          * in a change_notify msg.  Remember that a PCN message
1426          * includes the handle returned for the srv_spoolss_replyopenprinter()
1427          * call.  Therefore messages are grouped according to printer handle.
1428          */
1429
1430         for ( i=0; i<msg_count; i++ ) {
1431                 struct timeval msg_tv;
1432
1433                 if (msg_ptr + 4 - buf > data->length) {
1434                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1435                         return;
1436                 }
1437
1438                 msg_len = IVAL(msg_ptr,0);
1439                 msg_ptr += 4;
1440
1441                 if (msg_ptr + msg_len - buf > data->length) {
1442                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1443                         return;
1444                 }
1445
1446                 /* unpack messages */
1447
1448                 ZERO_STRUCT( notify );
1449                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1450                 msg_ptr += msg_len;
1451
1452                 /* add to correct list in container */
1453
1454                 notify_msg_ctr_addmsg( &messages, &notify );
1455
1456                 /* free memory that might have been allocated by notify2_unpack_msg() */
1457
1458                 if ( notify.len != 0 )
1459                         SAFE_FREE( notify.notify.data );
1460         }
1461
1462         /* process each group of messages */
1463
1464         num_groups = notify_msg_ctr_numgroups( &messages );
1465         for ( i=0; i<num_groups; i++ )
1466                 send_notify2_changes( &messages, i );
1467
1468
1469         /* cleanup */
1470
1471         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1472                 (uint32_t)msg_count ));
1473
1474         notify_msg_ctr_destroy( &messages );
1475
1476         return;
1477 }
1478
1479 /********************************************************************
1480  Send a message to ourself about new driver being installed
1481  so we can upgrade the information for each printer bound to this
1482  driver
1483  ********************************************************************/
1484
1485 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1486                                             struct messaging_context *msg_ctx)
1487 {
1488         int len = strlen(drivername);
1489
1490         if (!len)
1491                 return false;
1492
1493         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1494                 drivername));
1495
1496         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1497                            MSG_PRINTER_DRVUPGRADE,
1498                            (const uint8_t *)drivername, len+1);
1499
1500         return true;
1501 }
1502
1503 void srv_spoolss_cleanup(void)
1504 {
1505         struct printer_session_counter *session_counter;
1506
1507         for (session_counter = counter_list;
1508              session_counter != NULL;
1509              session_counter = counter_list) {
1510                 DLIST_REMOVE(counter_list, session_counter);
1511                 TALLOC_FREE(session_counter);
1512         }
1513 }
1514
1515 /**********************************************************************
1516  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1517  over all printers, upgrading ones as necessary
1518  **********************************************************************/
1519
1520 void do_drv_upgrade_printer(struct messaging_context *msg,
1521                             void *private_data,
1522                             uint32_t msg_type,
1523                             struct server_id server_id,
1524                             DATA_BLOB *data)
1525 {
1526         TALLOC_CTX *tmp_ctx;
1527         const struct auth_session_info *session_info = get_session_info_system();
1528         struct spoolss_PrinterInfo2 *pinfo2;
1529         WERROR result;
1530         const char *drivername;
1531         int snum;
1532         int n_services = lp_numservices();
1533         struct dcerpc_binding_handle *b = NULL;
1534
1535         tmp_ctx = talloc_new(NULL);
1536         if (!tmp_ctx) return;
1537
1538         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1539         if (!drivername) {
1540                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1541                 goto done;
1542         }
1543
1544         DEBUG(10, ("do_drv_upgrade_printer: "
1545                    "Got message for new driver [%s]\n", drivername));
1546
1547         /* Iterate the printer list */
1548
1549         for (snum = 0; snum < n_services; snum++) {
1550                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1551                         continue;
1552                 }
1553
1554                 /* ignore [printers] share */
1555                 if (strequal(lp_const_servicename(snum), "printers")) {
1556                         continue;
1557                 }
1558
1559                 if (b == NULL) {
1560                         result = winreg_printer_binding_handle(tmp_ctx,
1561                                                                session_info,
1562                                                                msg,
1563                                                                &b);
1564                         if (!W_ERROR_IS_OK(result)) {
1565                                 break;
1566                         }
1567                 }
1568
1569                 result = winreg_get_printer(tmp_ctx, b,
1570                                             lp_const_servicename(snum),
1571                                             &pinfo2);
1572
1573                 if (!W_ERROR_IS_OK(result)) {
1574                         continue;
1575                 }
1576
1577                 if (!pinfo2->drivername) {
1578                         continue;
1579                 }
1580
1581                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1582                         continue;
1583                 }
1584
1585                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1586
1587                 /* all we care about currently is the change_id */
1588                 result = winreg_printer_update_changeid(tmp_ctx, b,
1589                                                         pinfo2->printername);
1590
1591                 if (!W_ERROR_IS_OK(result)) {
1592                         DEBUG(3, ("do_drv_upgrade_printer: "
1593                                   "Failed to update changeid [%s]\n",
1594                                   win_errstr(result)));
1595                 }
1596         }
1597
1598         /* all done */
1599 done:
1600         talloc_free(tmp_ctx);
1601 }
1602
1603 /********************************************************************
1604  Update the cache for all printq's with a registered client
1605  connection
1606  ********************************************************************/
1607
1608 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1609 {
1610         struct printer_handle *printer = printers_list;
1611         int snum;
1612
1613         /* loop through all printers and update the cache where
1614            a client is connected */
1615         while (printer) {
1616                 if ((printer->printer_type == SPLHND_PRINTER) &&
1617                     ((printer->notify.cli_chan != NULL) &&
1618                      (printer->notify.cli_chan->active_connections > 0))) {
1619                         snum = print_queue_snum(printer->sharename);
1620                         print_queue_status(msg_ctx, snum, NULL, NULL);
1621                 }
1622
1623                 printer = printer->next;
1624         }
1625
1626         return;
1627 }
1628
1629 /****************************************************************
1630  _spoolss_OpenPrinter
1631 ****************************************************************/
1632
1633 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1634                             struct spoolss_OpenPrinter *r)
1635 {
1636         struct spoolss_OpenPrinterEx e;
1637         struct spoolss_UserLevel1 level1;
1638         WERROR werr;
1639
1640         ZERO_STRUCT(level1);
1641
1642         e.in.printername        = r->in.printername;
1643         e.in.datatype           = r->in.datatype;
1644         e.in.devmode_ctr        = r->in.devmode_ctr;
1645         e.in.access_mask        = r->in.access_mask;
1646         e.in.userlevel_ctr.level                = 1;
1647         e.in.userlevel_ctr.user_info.level1     = &level1;
1648
1649         e.out.handle            = r->out.handle;
1650
1651         werr = _spoolss_OpenPrinterEx(p, &e);
1652
1653         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1654                 /* OpenPrinterEx returns this for a bad
1655                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1656                  * instead.
1657                  */
1658                 werr = WERR_INVALID_PRINTER_NAME;
1659         }
1660
1661         return werr;
1662 }
1663
1664 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1665                               struct spoolss_DeviceMode *orig,
1666                               struct spoolss_DeviceMode **dest)
1667 {
1668         struct spoolss_DeviceMode *dm;
1669
1670         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1671         if (!dm) {
1672                 return WERR_NOMEM;
1673         }
1674
1675         /* copy all values, then duplicate strings and structs */
1676         *dm = *orig;
1677
1678         dm->devicename = talloc_strdup(dm, orig->devicename);
1679         if (!dm->devicename) {
1680                 return WERR_NOMEM;
1681         }
1682         dm->formname = talloc_strdup(dm, orig->formname);
1683         if (!dm->formname) {
1684                 return WERR_NOMEM;
1685         }
1686         if (orig->driverextra_data.data) {
1687                 dm->driverextra_data.data =
1688                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1689                                         orig->driverextra_data.length);
1690                 if (!dm->driverextra_data.data) {
1691                         return WERR_NOMEM;
1692                 }
1693         }
1694
1695         *dest = dm;
1696         return WERR_OK;
1697 }
1698
1699 /****************************************************************
1700  _spoolss_OpenPrinterEx
1701 ****************************************************************/
1702
1703 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1704                               struct spoolss_OpenPrinterEx *r)
1705 {
1706         int snum;
1707         char *raddr;
1708         char *rhost;
1709         struct printer_handle *Printer=NULL;
1710         WERROR result;
1711         int rc;
1712
1713         if (!r->in.printername) {
1714                 return WERR_INVALID_PARAM;
1715         }
1716
1717         if (!*r->in.printername) {
1718                 return WERR_INVALID_PARAM;
1719         }
1720
1721         if (r->in.userlevel_ctr.level > 3) {
1722                 return WERR_INVALID_PARAM;
1723         }
1724         if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1725             (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1726             (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1727                 return WERR_INVALID_PARAM;
1728         }
1729
1730         /* some sanity check because you can open a printer or a print server */
1731         /* aka: \\server\printer or \\server */
1732
1733         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1734
1735         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1736         if (!W_ERROR_IS_OK(result)) {
1737                 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1738                         "for printer %s\n", r->in.printername));
1739                 ZERO_STRUCTP(r->out.handle);
1740                 return result;
1741         }
1742
1743         Printer = find_printer_index_by_hnd(p, r->out.handle);
1744         if ( !Printer ) {
1745                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1746                         "handle we created for printer %s\n", r->in.printername));
1747                 close_printer_handle(p, r->out.handle);
1748                 ZERO_STRUCTP(r->out.handle);
1749                 return WERR_INVALID_PARAM;
1750         }
1751
1752         /*
1753          * First case: the user is opening the print server:
1754          *
1755          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1756          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1757          *
1758          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1759          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1760          * or if the user is listed in the smb.conf printer admin parameter.
1761          *
1762          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1763          * client view printer folder, but does not show the MSAPW.
1764          *
1765          * Note: this test needs code to check access rights here too. Jeremy
1766          * could you look at this?
1767          *
1768          * Second case: the user is opening a printer:
1769          * NT doesn't let us connect to a printer if the connecting user
1770          * doesn't have print permission.
1771          *
1772          * Third case: user is opening a Port Monitor
1773          * access checks same as opening a handle to the print server.
1774          */
1775
1776         switch (Printer->printer_type )
1777         {
1778         case SPLHND_SERVER:
1779         case SPLHND_PORTMON_TCP:
1780         case SPLHND_PORTMON_LOCAL:
1781                 /* Printserver handles use global struct... */
1782
1783                 snum = -1;
1784
1785                 /* Map standard access rights to object specific access rights */
1786
1787                 se_map_standard(&r->in.access_mask,
1788                                 &printserver_std_mapping);
1789
1790                 /* Deny any object specific bits that don't apply to print
1791                    servers (i.e printer and job specific bits) */
1792
1793                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1794
1795                 if (r->in.access_mask &
1796                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1797                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1798                         close_printer_handle(p, r->out.handle);
1799                         ZERO_STRUCTP(r->out.handle);
1800                         return WERR_ACCESS_DENIED;
1801                 }
1802
1803                 /* Allow admin access */
1804
1805                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1806                 {
1807                         if (!lp_ms_add_printer_wizard()) {
1808                                 close_printer_handle(p, r->out.handle);
1809                                 ZERO_STRUCTP(r->out.handle);
1810                                 return WERR_ACCESS_DENIED;
1811                         }
1812
1813                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1814                            and not a printer admin, then fail */
1815
1816                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1817                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1818                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1819                                                 p->session_info->security_token)) {
1820                                 close_printer_handle(p, r->out.handle);
1821                                 ZERO_STRUCTP(r->out.handle);
1822                                 DEBUG(3,("access DENIED as user is not root, "
1823                                         "has no printoperator privilege, "
1824                                         "not a member of the printoperator builtin group and "
1825                                         "is not in printer admin list"));
1826                                 return WERR_ACCESS_DENIED;
1827                         }
1828
1829                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1830                 }
1831                 else
1832                 {
1833                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1834                 }
1835
1836                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1837                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1838
1839                 /* We fall through to return WERR_OK */
1840                 break;
1841
1842         case SPLHND_PRINTER:
1843                 /* NT doesn't let us connect to a printer if the connecting user
1844                    doesn't have print permission.  */
1845
1846                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1847                         close_printer_handle(p, r->out.handle);
1848                         ZERO_STRUCTP(r->out.handle);
1849                         return WERR_BADFID;
1850                 }
1851
1852                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1853                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1854                 }
1855
1856                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1857
1858                 /* map an empty access mask to the minimum access mask */
1859                 if (r->in.access_mask == 0x0)
1860                         r->in.access_mask = PRINTER_ACCESS_USE;
1861
1862                 /*
1863                  * If we are not serving the printer driver for this printer,
1864                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1865                  * will keep NT clients happy  --jerry
1866                  */
1867
1868                 if (lp_use_client_driver(snum)
1869                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1870                 {
1871                         r->in.access_mask = PRINTER_ACCESS_USE;
1872                 }
1873
1874                 /* check smb.conf parameters and the the sec_desc */
1875                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1876                                                          p->mem_ctx);
1877                 if (raddr == NULL) {
1878                         return WERR_NOMEM;
1879                 }
1880
1881                 rc = get_remote_hostname(p->remote_address,
1882                                          &rhost,
1883                                          p->mem_ctx);
1884                 if (rc < 0) {
1885                         return WERR_NOMEM;
1886                 }
1887                 if (strequal(rhost, "UNKNOWN")) {
1888                         rhost = raddr;
1889                 }
1890
1891                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1892                                   rhost, raddr)) {
1893                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1894                         ZERO_STRUCTP(r->out.handle);
1895                         return WERR_ACCESS_DENIED;
1896                 }
1897
1898                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1899                                    p->session_info->security_token, snum) ||
1900                     !print_access_check(p->session_info,
1901                                         p->msg_ctx,
1902                                         snum,
1903                                         r->in.access_mask)) {
1904                         DEBUG(3, ("access DENIED for printer open\n"));
1905                         close_printer_handle(p, r->out.handle);
1906                         ZERO_STRUCTP(r->out.handle);
1907                         return WERR_ACCESS_DENIED;
1908                 }
1909
1910                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1911                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1912                         close_printer_handle(p, r->out.handle);
1913                         ZERO_STRUCTP(r->out.handle);
1914                         return WERR_ACCESS_DENIED;
1915                 }
1916
1917                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1918                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1919                 else
1920                         r->in.access_mask = PRINTER_ACCESS_USE;
1921
1922                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1923                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1924
1925                 winreg_create_printer_internal(p->mem_ctx,
1926                                       get_session_info_system(),
1927                                       p->msg_ctx,
1928                                       lp_const_servicename(snum));
1929
1930                 break;
1931
1932         default:
1933                 /* sanity check to prevent programmer error */
1934                 ZERO_STRUCTP(r->out.handle);
1935                 return WERR_BADFID;
1936         }
1937
1938         Printer->access_granted = r->in.access_mask;
1939
1940         /*
1941          * If the client sent a devmode in the OpenPrinter() call, then
1942          * save it here in case we get a job submission on this handle
1943          */
1944
1945          if ((Printer->printer_type != SPLHND_SERVER)
1946           && (r->in.devmode_ctr.devmode != NULL)) {
1947                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1948                                 &Printer->devmode);
1949          }
1950
1951         return WERR_OK;
1952 }
1953
1954 /****************************************************************
1955  _spoolss_ClosePrinter
1956 ****************************************************************/
1957
1958 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1959                              struct spoolss_ClosePrinter *r)
1960 {
1961         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1962
1963         if (Printer && Printer->document_started) {
1964                 struct spoolss_EndDocPrinter e;
1965
1966                 e.in.handle = r->in.handle;
1967
1968                 _spoolss_EndDocPrinter(p, &e);
1969         }
1970
1971         if (!close_printer_handle(p, r->in.handle))
1972                 return WERR_BADFID;
1973
1974         /* clear the returned printer handle.  Observed behavior
1975            from Win2k server.  Don't think this really matters.
1976            Previous code just copied the value of the closed
1977            handle.    --jerry */
1978
1979         ZERO_STRUCTP(r->out.handle);
1980
1981         return WERR_OK;
1982 }
1983
1984 /****************************************************************
1985  _spoolss_DeletePrinter
1986 ****************************************************************/
1987
1988 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1989                               struct spoolss_DeletePrinter *r)
1990 {
1991         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1992         WERROR result;
1993         int snum;
1994
1995         if (Printer && Printer->document_started) {
1996                 struct spoolss_EndDocPrinter e;
1997
1998                 e.in.handle = r->in.handle;
1999
2000                 _spoolss_EndDocPrinter(p, &e);
2001         }
2002
2003         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2004                 winreg_delete_printer_key_internal(p->mem_ctx,
2005                                           get_session_info_system(),
2006                                           p->msg_ctx,
2007                                           lp_const_servicename(snum),
2008                                           "");
2009         }
2010
2011         result = delete_printer_handle(p, r->in.handle);
2012
2013         return result;
2014 }
2015
2016 /*******************************************************************
2017  * static function to lookup the version id corresponding to an
2018  * long architecture string
2019  ******************************************************************/
2020
2021 static const struct print_architecture_table_node archi_table[]= {
2022
2023         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2024         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2025         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2026         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2027         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2028         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2029         {"Windows x64",          SPL_ARCH_X64,          3 },
2030         {NULL,                   "",            -1 }
2031 };
2032
2033 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2034                                    SPOOLSS_DRIVER_VERSION_NT35,
2035                                    SPOOLSS_DRIVER_VERSION_NT4,
2036                                    SPOOLSS_DRIVER_VERSION_200X,
2037                                    -1};
2038
2039 static int get_version_id(const char *arch)
2040 {
2041         int i;
2042
2043         for (i=0; archi_table[i].long_archi != NULL; i++)
2044         {
2045                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2046                         return (archi_table[i].version);
2047         }
2048
2049         return -1;
2050 }
2051
2052 /****************************************************************
2053  _spoolss_DeletePrinterDriver
2054 ****************************************************************/
2055
2056 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2057                                     struct spoolss_DeletePrinterDriver *r)
2058 {
2059
2060         struct spoolss_DriverInfo8 *info = NULL;
2061         int                             version;
2062         WERROR                          status;
2063         struct dcerpc_binding_handle *b;
2064         TALLOC_CTX *tmp_ctx = NULL;
2065         int i;
2066         bool found;
2067
2068         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2069            and not a printer admin, then fail */
2070
2071         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2072             !security_token_has_privilege(p->session_info->security_token,
2073                                           SEC_PRIV_PRINT_OPERATOR)) {
2074                 return WERR_ACCESS_DENIED;
2075         }
2076
2077         /* check that we have a valid driver name first */
2078
2079         if ((version = get_version_id(r->in.architecture)) == -1) {
2080                 return WERR_INVALID_ENVIRONMENT;
2081         }
2082
2083         tmp_ctx = talloc_new(p->mem_ctx);
2084         if (!tmp_ctx) {
2085                 return WERR_NOMEM;
2086         }
2087
2088         status = winreg_printer_binding_handle(tmp_ctx,
2089                                                get_session_info_system(),
2090                                                p->msg_ctx,
2091                                                &b);
2092         if (!W_ERROR_IS_OK(status)) {
2093                 goto done;
2094         }
2095
2096         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2097                 status = winreg_get_driver(tmp_ctx, b,
2098                                            r->in.architecture, r->in.driver,
2099                                            drv_cversion[i], &info);
2100                 if (!W_ERROR_IS_OK(status)) {
2101                         DEBUG(5, ("skipping del of driver with version %d\n",
2102                                   drv_cversion[i]));
2103                         continue;
2104                 }
2105                 found = true;
2106
2107                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2108                         status = WERR_PRINTER_DRIVER_IN_USE;
2109                         goto done;
2110                 }
2111
2112                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2113                 if (!W_ERROR_IS_OK(status)) {
2114                         DEBUG(0, ("failed del of driver with version %d\n",
2115                                   drv_cversion[i]));
2116                         goto done;
2117                 }
2118         }
2119         if (found == false) {
2120                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2121                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2122         } else {
2123                 status = WERR_OK;
2124         }
2125
2126 done:
2127         talloc_free(tmp_ctx);
2128
2129         return status;
2130 }
2131
2132 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2133                                   struct pipes_struct *p,
2134                                   struct spoolss_DeletePrinterDriverEx *r,
2135                                   struct dcerpc_binding_handle *b,
2136                                   struct spoolss_DriverInfo8 *info)
2137 {
2138         WERROR status;
2139         bool delete_files;
2140
2141         if (printer_driver_in_use(mem_ctx, b, info)) {
2142                 status = WERR_PRINTER_DRIVER_IN_USE;
2143                 goto done;
2144         }
2145
2146         /*
2147          * we have a couple of cases to consider.
2148          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2149          *     then the delete should fail if **any** files overlap with
2150          *     other drivers
2151          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2152          *     non-overlapping files
2153          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2154          *     are set, then do not delete any files
2155          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2156          */
2157
2158         delete_files = r->in.delete_flags
2159                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2160
2161
2162         if (delete_files) {
2163                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2164                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2165                         status = WERR_PRINTER_DRIVER_IN_USE;
2166                         goto done;
2167                 }
2168                 /*
2169                  * printer_driver_files_in_use() has trimmed overlapping files
2170                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2171                  */
2172         }
2173
2174
2175         status = winreg_del_driver(mem_ctx, b, info, info->version);
2176         if (!W_ERROR_IS_OK(status)) {
2177                 goto done;
2178         }
2179
2180         /*
2181          * now delete any associated files if delete_files is
2182          * true. Even if this part failes, we return succes
2183          * because the driver doesn not exist any more
2184          */
2185         if (delete_files) {
2186                 delete_driver_files(p->session_info, info);
2187         }
2188
2189 done:
2190         return status;
2191 }
2192
2193 /****************************************************************
2194  _spoolss_DeletePrinterDriverEx
2195 ****************************************************************/
2196
2197 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2198                                       struct spoolss_DeletePrinterDriverEx *r)
2199 {
2200         struct spoolss_DriverInfo8 *info = NULL;
2201         WERROR                          status;
2202         struct dcerpc_binding_handle *b;
2203         TALLOC_CTX *tmp_ctx = NULL;
2204         int i;
2205         bool found;
2206
2207         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2208            and not a printer admin, then fail */
2209
2210         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2211             !security_token_has_privilege(p->session_info->security_token,
2212                                           SEC_PRIV_PRINT_OPERATOR)) {
2213                 return WERR_ACCESS_DENIED;
2214         }
2215
2216         /* check that we have a valid driver name first */
2217         if (get_version_id(r->in.architecture) == -1) {
2218                 /* this is what NT returns */
2219                 return WERR_INVALID_ENVIRONMENT;
2220         }
2221
2222         tmp_ctx = talloc_new(p->mem_ctx);
2223         if (!tmp_ctx) {
2224                 return WERR_NOMEM;
2225         }
2226
2227         status = winreg_printer_binding_handle(tmp_ctx,
2228                                                get_session_info_system(),
2229                                                p->msg_ctx,
2230                                                &b);
2231         if (!W_ERROR_IS_OK(status)) {
2232                 goto done;
2233         }
2234
2235         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2236                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2237                  && (drv_cversion[i] != r->in.version)) {
2238                         continue;
2239                 }
2240
2241                 /* check if a driver with this version exists before delete */
2242                 status = winreg_get_driver(tmp_ctx, b,
2243                                            r->in.architecture, r->in.driver,
2244                                            drv_cversion[i], &info);
2245                 if (!W_ERROR_IS_OK(status)) {
2246                         DEBUG(5, ("skipping del of driver with version %d\n",
2247                                   drv_cversion[i]));
2248                         continue;
2249                 }
2250                 found = true;
2251
2252                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2253                 if (!W_ERROR_IS_OK(status)) {
2254                         DEBUG(0, ("failed to delete driver with version %d\n",
2255                                   drv_cversion[i]));
2256                         goto done;
2257                 }
2258         }
2259         if (found == false) {
2260                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2261                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2262         } else {
2263                 status = WERR_OK;
2264         }
2265
2266 done:
2267         talloc_free(tmp_ctx);
2268         return status;
2269 }
2270
2271
2272 /********************************************************************
2273  GetPrinterData on a printer server Handle.
2274 ********************************************************************/
2275
2276 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2277                                             const char *value,
2278                                             enum winreg_Type *type,
2279                                             union spoolss_PrinterData *data)
2280 {
2281         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2282
2283         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2284                 *type = REG_DWORD;
2285                 SIVAL(&data->value, 0, 0x00);
2286                 return WERR_OK;
2287         }
2288
2289         if (!strcasecmp_m(value, "BeepEnabled")) {
2290                 *type = REG_DWORD;
2291                 SIVAL(&data->value, 0, 0x00);
2292                 return WERR_OK;
2293         }
2294
2295         if (!strcasecmp_m(value, "EventLog")) {
2296                 *type = REG_DWORD;
2297                 /* formally was 0x1b */
2298                 SIVAL(&data->value, 0, 0x00);
2299                 return WERR_OK;
2300         }
2301
2302         if (!strcasecmp_m(value, "NetPopup")) {
2303                 *type = REG_DWORD;
2304                 SIVAL(&data->value, 0, 0x00);
2305                 return WERR_OK;
2306         }
2307
2308         if (!strcasecmp_m(value, "MajorVersion")) {
2309                 *type = REG_DWORD;
2310
2311                 /* Windows NT 4.0 seems to not allow uploading of drivers
2312                    to a server that reports 0x3 as the MajorVersion.
2313                    need to investigate more how Win2k gets around this .
2314                    -- jerry */
2315
2316                 if (RA_WINNT == get_remote_arch()) {
2317                         SIVAL(&data->value, 0, 0x02);
2318                 } else {
2319                         SIVAL(&data->value, 0, 0x03);
2320                 }
2321
2322                 return WERR_OK;
2323         }
2324
2325         if (!strcasecmp_m(value, "MinorVersion")) {
2326                 *type = REG_DWORD;
2327                 SIVAL(&data->value, 0, 0x00);
2328                 return WERR_OK;
2329         }
2330
2331         /* REG_BINARY
2332          *  uint32_t size        = 0x114
2333          *  uint32_t major       = 5
2334          *  uint32_t minor       = [0|1]
2335          *  uint32_t build       = [2195|2600]
2336          *  extra unicode string = e.g. "Service Pack 3"
2337          */
2338         if (!strcasecmp_m(value, "OSVersion")) {
2339                 DATA_BLOB blob;
2340                 enum ndr_err_code ndr_err;
2341                 struct spoolss_OSVersion os;
2342
2343                 os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
2344                                                       "spoolss", "os_major", 5);
2345                                                       /* Windows 2000 == 5.0 */
2346                 os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
2347                                                       "spoolss", "os_minor", 0);
2348                 os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
2349                                                       "spoolss", "os_build", 2195);
2350                 os.extra_string         = "";   /* leave extra string empty */
2351
2352                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2353                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2354                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2355                         return WERR_GENERAL_FAILURE;
2356                 }
2357
2358                 if (DEBUGLEVEL >= 10) {
2359                         NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2360                 }
2361
2362                 *type = REG_BINARY;
2363                 data->binary = blob;
2364
2365                 return WERR_OK;
2366         }
2367
2368
2369         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2370                 *type = REG_SZ;
2371
2372                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2373                 W_ERROR_HAVE_NO_MEMORY(data->string);
2374
2375                 return WERR_OK;
2376         }
2377
2378         if (!strcasecmp_m(value, "Architecture")) {
2379                 *type = REG_SZ;
2380                 data->string = talloc_strdup(mem_ctx,
2381                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2382                 W_ERROR_HAVE_NO_MEMORY(data->string);
2383
2384                 return WERR_OK;
2385         }
2386
2387         if (!strcasecmp_m(value, "DsPresent")) {
2388                 *type = REG_DWORD;
2389
2390                 /* only show the publish check box if we are a
2391                    member of a AD domain */
2392
2393                 if (lp_security() == SEC_ADS) {
2394                         SIVAL(&data->value, 0, 0x01);
2395                 } else {
2396                         SIVAL(&data->value, 0, 0x00);
2397                 }
2398                 return WERR_OK;
2399         }
2400
2401         if (!strcasecmp_m(value, "DNSMachineName")) {
2402                 const char *hostname = get_mydnsfullname();
2403
2404                 if (!hostname) {
2405                         return WERR_BADFILE;
2406                 }
2407
2408                 *type = REG_SZ;
2409                 data->string = talloc_strdup(mem_ctx, hostname);
2410                 W_ERROR_HAVE_NO_MEMORY(data->string);
2411
2412                 return WERR_OK;
2413         }
2414
2415         *type = REG_NONE;
2416
2417         return WERR_INVALID_PARAM;
2418 }
2419
2420 /****************************************************************
2421  _spoolss_GetPrinterData
2422 ****************************************************************/
2423
2424 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2425                                struct spoolss_GetPrinterData *r)
2426 {
2427         struct spoolss_GetPrinterDataEx r2;
2428
2429         r2.in.handle            = r->in.handle;
2430         r2.in.key_name          = "PrinterDriverData";
2431         r2.in.value_name        = r->in.value_name;
2432         r2.in.offered           = r->in.offered;
2433         r2.out.type             = r->out.type;
2434         r2.out.data             = r->out.data;
2435         r2.out.needed           = r->out.needed;
2436
2437         return _spoolss_GetPrinterDataEx(p, &r2);
2438 }
2439
2440 /*********************************************************
2441  Connect to the client machine.
2442 **********************************************************/
2443
2444 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2445                                       struct sockaddr_storage *client_ss, const char *remote_machine)
2446 {
2447         NTSTATUS ret;
2448         struct sockaddr_storage rm_addr;
2449         char addr[INET6_ADDRSTRLEN];
2450
2451         if ( is_zero_addr(client_ss) ) {
2452                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2453                         remote_machine));
2454                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2455                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2456                         return false;
2457                 }
2458                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2459         } else {
2460                 rm_addr = *client_ss;
2461                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2462                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2463                         addr));
2464         }
2465
2466         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2467                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2468                         addr));
2469                 return false;
2470         }
2471
2472         /* setup the connection */
2473         ret = cli_full_connection( pp_cli, lp_netbios_name(), remote_machine,
2474                 &rm_addr, 0, "IPC$", "IPC",
2475                 "", /* username */
2476                 "", /* domain */
2477                 "", /* password */
2478                 0, lp_client_signing());
2479
2480         if ( !NT_STATUS_IS_OK( ret ) ) {
2481                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2482                         remote_machine ));
2483                 return false;
2484         }
2485
2486         if ( smbXcli_conn_protocol((*pp_cli)->conn) != PROTOCOL_NT1 ) {
2487                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2488                 cli_shutdown(*pp_cli);
2489                 return false;
2490         }
2491
2492         /*
2493          * Ok - we have an anonymous connection to the IPC$ share.
2494          * Now start the NT Domain stuff :-).
2495          */
2496
2497         ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2498         if (!NT_STATUS_IS_OK(ret)) {
2499                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2500                         remote_machine, nt_errstr(ret)));
2501                 cli_shutdown(*pp_cli);
2502                 return false;
2503         }
2504
2505         return true;
2506 }
2507
2508 /***************************************************************************
2509  Connect to the client.
2510 ****************************************************************************/
2511
2512 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2513                                         uint32_t localprinter,
2514                                         enum winreg_Type type,
2515                                         struct policy_handle *handle,
2516                                         struct notify_back_channel **_chan,
2517                                         struct sockaddr_storage *client_ss,
2518                                         struct messaging_context *msg_ctx)
2519 {
2520         WERROR result;
2521         NTSTATUS status;
2522         struct notify_back_channel *chan;
2523
2524         for (chan = back_channels; chan; chan = chan->next) {
2525                 if (memcmp(&chan->client_address, client_ss,
2526                            sizeof(struct sockaddr_storage)) == 0) {
2527                         break;
2528                 }
2529         }
2530
2531         /*
2532          * If it's the first connection, contact the client
2533          * and connect to the IPC$ share anonymously
2534          */
2535         if (!chan) {
2536                 fstring unix_printer;
2537
2538                 /* the +2 is to strip the leading 2 backslashs */
2539                 fstrcpy(unix_printer, printer + 2);
2540
2541                 chan = talloc_zero(NULL, struct notify_back_channel);
2542                 if (!chan) {
2543                         return false;
2544                 }
2545                 chan->client_address = *client_ss;
2546
2547                 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2548                         TALLOC_FREE(chan);
2549                         return false;
2550                 }
2551
2552                 DLIST_ADD(back_channels, chan);
2553
2554                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2555                                    receive_notify2_message_list);
2556         }
2557
2558         if (chan->cli_pipe == NULL ||
2559             chan->cli_pipe->binding_handle == NULL) {
2560                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2561                         "NULL %s for printer %s\n",
2562                         chan->cli_pipe == NULL ?
2563                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2564                         printer));
2565                 return false;
2566         }
2567
2568         /*
2569          * Tell the specific printing tdb we want messages for this printer
2570          * by registering our PID.
2571          */
2572
2573         if (!print_notify_register_pid(snum)) {
2574                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2575                           printer));
2576         }
2577
2578         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2579                                                  talloc_tos(),
2580                                                  printer,
2581                                                  localprinter,
2582                                                  type,
2583                                                  0,
2584                                                  NULL,
2585                                                  handle,
2586                                                  &result);
2587         if (!NT_STATUS_IS_OK(status)) {
2588                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2589                 result = ntstatus_to_werror(status);
2590         } else if (!W_ERROR_IS_OK(result)) {
2591                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2592         }
2593
2594         chan->active_connections++;
2595         *_chan = chan;
2596
2597         return (W_ERROR_IS_OK(result));
2598 }
2599
2600 /****************************************************************
2601  ****************************************************************/
2602
2603 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2604                                                              const struct spoolss_NotifyOption *r)
2605 {
2606         struct spoolss_NotifyOption *option;
2607         uint32_t i,k;
2608
2609         if (!r) {
2610                 return NULL;
2611         }
2612
2613         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2614         if (!option) {
2615                 return NULL;
2616         }
2617
2618         *option = *r;
2619
2620         if (!option->count) {
2621                 return option;
2622         }
2623
2624         option->types = talloc_zero_array(option,
2625                 struct spoolss_NotifyOptionType, option->count);
2626         if (!option->types) {
2627                 talloc_free(option);
2628                 return NULL;
2629         }
2630
2631         for (i=0; i < option->count; i++) {
2632                 option->types[i] = r->types[i];
2633
2634                 if (option->types[i].count) {
2635                         option->types[i].fields = talloc_zero_array(option,
2636                                 union spoolss_Field, option->types[i].count);
2637                         if (!option->types[i].fields) {
2638                                 talloc_free(option);
2639                                 return NULL;
2640                         }
2641                         for (k=0; k<option->types[i].count; k++) {
2642                                 option->types[i].fields[k] =
2643                                         r->types[i].fields[k];
2644                         }
2645                 }
2646         }
2647
2648         return option;
2649 }
2650
2651 /****************************************************************
2652  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2653  *
2654  * before replying OK: status=0 a rpc call is made to the workstation
2655  * asking ReplyOpenPrinter
2656  *
2657  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2658  * called from api_spoolss_rffpcnex
2659 ****************************************************************/
2660
2661 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2662                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2663 {
2664         int snum = -1;
2665         struct spoolss_NotifyOption *option = r->in.notify_options;
2666         struct sockaddr_storage client_ss;
2667         ssize_t client_len;
2668
2669         /* store the notify value in the printer struct */
2670
2671         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2672
2673         if (!Printer) {
2674                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2675                         "Invalid handle (%s:%u:%u).\n",
2676                         OUR_HANDLE(r->in.handle)));
2677                 return WERR_BADFID;
2678         }
2679
2680         Printer->notify.flags           = r->in.flags;
2681         Printer->notify.options         = r->in.options;
2682         Printer->notify.printerlocal    = r->in.printer_local;
2683         Printer->notify.msg_ctx         = p->msg_ctx;
2684
2685         TALLOC_FREE(Printer->notify.option);
2686         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2687
2688         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2689
2690         /* Connect to the client machine and send a ReplyOpenPrinter */
2691
2692         if ( Printer->printer_type == SPLHND_SERVER)
2693                 snum = -1;
2694         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2695                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2696                 return WERR_BADFID;
2697
2698         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2699                   "remote_address is %s\n",
2700                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2701
2702         if (!lp_print_notify_backchannel(snum)) {
2703                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2704                         "backchannel disabled\n"));
2705                 return WERR_SERVER_UNAVAILABLE;
2706         }
2707
2708         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2709                                                   (struct sockaddr *) &client_ss,
2710                                                   sizeof(struct sockaddr_storage));
2711         if (client_len < 0) {
2712                 return WERR_NOMEM;
2713         }
2714
2715         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2716                                         Printer->notify.printerlocal, REG_SZ,
2717                                         &Printer->notify.cli_hnd,
2718                                         &Printer->notify.cli_chan,
2719                                         &client_ss, p->msg_ctx)) {
2720                 return WERR_SERVER_UNAVAILABLE;
2721         }
2722
2723         return WERR_OK;
2724 }
2725
2726 /*******************************************************************
2727  * fill a notify_info_data with the servername
2728  ********************************************************************/
2729
2730 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2731                                        int snum,
2732                                        struct spoolss_Notify *data,
2733                                        print_queue_struct *queue,
2734                                        struct spoolss_PrinterInfo2 *pinfo2,
2735                                        TALLOC_CTX *mem_ctx)
2736 {
2737         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2738 }
2739
2740 /*******************************************************************
2741  * fill a notify_info_data with the printername (not including the servername).
2742  ********************************************************************/
2743
2744 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2745                                         int snum,
2746                                         struct spoolss_Notify *data,
2747                                         print_queue_struct *queue,
2748                                         struct spoolss_PrinterInfo2 *pinfo2,
2749                                         TALLOC_CTX *mem_ctx)
2750 {
2751         /* the notify name should not contain the \\server\ part */
2752         const char *p = strrchr(pinfo2->printername, '\\');
2753
2754         if (!p) {
2755                 p = pinfo2->printername;
2756         } else {
2757                 p++;
2758         }
2759
2760         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2761 }
2762
2763 /*******************************************************************
2764  * fill a notify_info_data with the servicename
2765  ********************************************************************/
2766
2767 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2768                                       int snum,
2769                                       struct spoolss_Notify *data,
2770                                       print_queue_struct *queue,
2771                                       struct spoolss_PrinterInfo2 *pinfo2,
2772                                       TALLOC_CTX *mem_ctx)
2773 {
2774         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2775 }
2776
2777 /*******************************************************************
2778  * fill a notify_info_data with the port name
2779  ********************************************************************/
2780
2781 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2782                                      int snum,
2783                                      struct spoolss_Notify *data,
2784                                      print_queue_struct *queue,
2785                                      struct spoolss_PrinterInfo2 *pinfo2,
2786                                      TALLOC_CTX *mem_ctx)
2787 {
2788         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2789 }
2790
2791 /*******************************************************************
2792  * fill a notify_info_data with the printername
2793  * but it doesn't exist, have to see what to do
2794  ********************************************************************/
2795
2796 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2797                                        int snum,
2798                                        struct spoolss_Notify *data,
2799                                        print_queue_struct *queue,
2800                                        struct spoolss_PrinterInfo2 *pinfo2,
2801                                        TALLOC_CTX *mem_ctx)
2802 {
2803         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2804 }
2805
2806 /*******************************************************************
2807  * fill a notify_info_data with the comment
2808  ********************************************************************/
2809
2810 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2811                                    int snum,
2812                                    struct spoolss_Notify *data,
2813                                    print_queue_struct *queue,
2814                                    struct spoolss_PrinterInfo2 *pinfo2,
2815                                    TALLOC_CTX *mem_ctx)
2816 {
2817         const char *p;
2818
2819         if (*pinfo2->comment == '\0') {
2820                 p = lp_comment(talloc_tos(), snum);
2821         } else {
2822                 p = pinfo2->comment;
2823         }
2824
2825         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2826 }
2827
2828 /*******************************************************************
2829  * fill a notify_info_data with the comment
2830  * location = "Room 1, floor 2, building 3"
2831  ********************************************************************/
2832
2833 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2834                                     int snum,
2835                                     struct spoolss_Notify *data,
2836                                     print_queue_struct *queue,
2837                                     struct spoolss_PrinterInfo2 *pinfo2,
2838                                     TALLOC_CTX *mem_ctx)
2839 {
2840         const char *loc = pinfo2->location;
2841         NTSTATUS status;
2842
2843         status = printer_list_get_printer(mem_ctx,
2844                                           pinfo2->sharename,
2845                                           NULL,
2846                                           &loc,
2847                                           NULL);
2848         if (NT_STATUS_IS_OK(status)) {
2849                 if (loc == NULL) {
2850                         loc = pinfo2->location;
2851                 }
2852         }
2853
2854         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2855 }
2856
2857 /*******************************************************************
2858  * fill a notify_info_data with the device mode
2859  * jfm:xxxx don't to it for know but that's a real problem !!!
2860  ********************************************************************/
2861
2862 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2863                                    int snum,
2864                                    struct spoolss_Notify *data,
2865                                    print_queue_struct *queue,
2866                                    struct spoolss_PrinterInfo2 *pinfo2,
2867                                    TALLOC_CTX *mem_ctx)
2868 {
2869         /* for a dummy implementation we have to zero the fields */
2870         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2871 }
2872
2873 /*******************************************************************
2874  * fill a notify_info_data with the separator file name
2875  ********************************************************************/
2876
2877 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2878                                    int snum,
2879                                    struct spoolss_Notify *data,
2880                                    print_queue_struct *queue,
2881                                    struct spoolss_PrinterInfo2 *pinfo2,
2882                                    TALLOC_CTX *mem_ctx)
2883 {
2884         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2885 }
2886
2887 /*******************************************************************
2888  * fill a notify_info_data with the print processor
2889  * jfm:xxxx return always winprint to indicate we don't do anything to it
2890  ********************************************************************/
2891
2892 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2893                                            int snum,
2894                                            struct spoolss_Notify *data,
2895                                            print_queue_struct *queue,
2896                                            struct spoolss_PrinterInfo2 *pinfo2,
2897                                            TALLOC_CTX *mem_ctx)
2898 {
2899         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2900 }
2901
2902 /*******************************************************************
2903  * fill a notify_info_data with the print processor options
2904  * jfm:xxxx send an empty string
2905  ********************************************************************/
2906
2907 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2908                                       int snum,
2909                                       struct spoolss_Notify *data,
2910                                       print_queue_struct *queue,
2911                                       struct spoolss_PrinterInfo2 *pinfo2,
2912                                       TALLOC_CTX *mem_ctx)
2913 {
2914         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2915 }
2916
2917 /*******************************************************************
2918  * fill a notify_info_data with the data type
2919  * jfm:xxxx always send RAW as data type
2920  ********************************************************************/
2921
2922 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2923                                     int snum,
2924                                     struct spoolss_Notify *data,
2925                                     print_queue_struct *queue,
2926                                     struct spoolss_PrinterInfo2 *pinfo2,
2927                                     TALLOC_CTX *mem_ctx)
2928 {
2929         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2930 }
2931
2932 /*******************************************************************
2933  * fill a notify_info_data with the security descriptor
2934  * jfm:xxxx send an null pointer to say no security desc
2935  * have to implement security before !
2936  ********************************************************************/
2937
2938 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2939                                          int snum,
2940                                          struct spoolss_Notify *data,
2941                                          print_queue_struct *queue,
2942                                          struct spoolss_PrinterInfo2 *pinfo2,
2943                                          TALLOC_CTX *mem_ctx)
2944 {
2945         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2946 }
2947
2948 /*******************************************************************
2949  * fill a notify_info_data with the attributes
2950  * jfm:xxxx a samba printer is always shared
2951  ********************************************************************/
2952
2953 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2954                                       int snum,
2955                                       struct spoolss_Notify *data,
2956                                       print_queue_struct *queue,
2957                                       struct spoolss_PrinterInfo2 *pinfo2,
2958                                       TALLOC_CTX *mem_ctx)
2959 {
2960         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2961 }
2962
2963 /*******************************************************************
2964  * fill a notify_info_data with the priority
2965  ********************************************************************/
2966
2967 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2968                                     int snum,
2969                                     struct spoolss_Notify *data,
2970                                     print_queue_struct *queue,
2971                                     struct spoolss_PrinterInfo2 *pinfo2,
2972                                     TALLOC_CTX *mem_ctx)
2973 {
2974         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2975 }
2976
2977 /*******************************************************************
2978  * fill a notify_info_data with the default priority
2979  ********************************************************************/
2980
2981 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2982                                             int snum,
2983                                             struct spoolss_Notify *data,
2984                                             print_queue_struct *queue,
2985                                             struct spoolss_PrinterInfo2 *pinfo2,
2986                                             TALLOC_CTX *mem_ctx)
2987 {
2988         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2989 }
2990
2991 /*******************************************************************
2992  * fill a notify_info_data with the start time
2993  ********************************************************************/
2994
2995 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2996                                       int snum,
2997                                       struct spoolss_Notify *data,
2998                                       print_queue_struct *queue,
2999                                       struct spoolss_PrinterInfo2 *pinfo2,
3000                                       TALLOC_CTX *mem_ctx)
3001 {
3002         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3003 }
3004
3005 /*******************************************************************
3006  * fill a notify_info_data with the until time
3007  ********************************************************************/
3008
3009 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3010                                       int snum,
3011                                       struct spoolss_Notify *data,
3012                                       print_queue_struct *queue,
3013                                       struct spoolss_PrinterInfo2 *pinfo2,
3014                                       TALLOC_CTX *mem_ctx)
3015 {
3016         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3017 }
3018
3019 /*******************************************************************
3020  * fill a notify_info_data with the status
3021  ********************************************************************/
3022
3023 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3024                                   int snum,
3025                                   struct spoolss_Notify *data,
3026                                   print_queue_struct *queue,
3027                                   struct spoolss_PrinterInfo2 *pinfo2,
3028                                   TALLOC_CTX *mem_ctx)
3029 {
3030         print_status_struct status;
3031
3032         print_queue_length(msg_ctx, snum, &status);
3033         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3034 }
3035
3036 /*******************************************************************
3037  * fill a notify_info_data with the number of jobs queued
3038  ********************************************************************/
3039
3040 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3041                                  int snum,
3042                                  struct spoolss_Notify *data,
3043                                  print_queue_struct *queue,
3044                                  struct spoolss_PrinterInfo2 *pinfo2,
3045                                  TALLOC_CTX *mem_ctx)
3046 {
3047         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3048                 data, print_queue_length(msg_ctx, snum, NULL));
3049 }
3050
3051 /*******************************************************************
3052  * fill a notify_info_data with the average ppm
3053  ********************************************************************/
3054
3055 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3056                                        int snum,
3057                                        struct spoolss_Notify *data,
3058                                        print_queue_struct *queue,
3059                                        struct spoolss_PrinterInfo2 *pinfo2,
3060                                        TALLOC_CTX *mem_ctx)
3061 {
3062         /* always respond 8 pages per minutes */
3063         /* a little hard ! */
3064         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3065 }
3066
3067 /*******************************************************************
3068  * fill a notify_info_data with username
3069  ********************************************************************/
3070
3071 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3072                                     int snum,
3073                                     struct spoolss_Notify *data,
3074                                     print_queue_struct *queue,
3075                                     struct spoolss_PrinterInfo2 *pinfo2,
3076                                     TALLOC_CTX *mem_ctx)
3077 {
3078         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3079 }
3080
3081 /*******************************************************************
3082  * fill a notify_info_data with job status
3083  ********************************************************************/
3084
3085 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3086                                       int snum,
3087                                       struct spoolss_Notify *data,
3088                                       print_queue_struct *queue,
3089                                       struct spoolss_PrinterInfo2 *pinfo2,
3090                                       TALLOC_CTX *mem_ctx)
3091 {
3092         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3093 }
3094
3095 /*******************************************************************
3096  * fill a notify_info_data with job name
3097  ********************************************************************/
3098
3099 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3100                                     int snum,
3101                                     struct spoolss_Notify *data,
3102                                     print_queue_struct *queue,
3103                                     struct spoolss_PrinterInfo2 *pinfo2,
3104                                     TALLOC_CTX *mem_ctx)
3105 {
3106         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3107 }
3108
3109 /*******************************************************************
3110  * fill a notify_info_data with job status
3111  ********************************************************************/
3112
3113 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3114                                              int snum,
3115                                              struct spoolss_Notify *data,
3116                                              print_queue_struct *queue,
3117                                              struct spoolss_PrinterInfo2 *pinfo2,
3118                                              TALLOC_CTX *mem_ctx)
3119 {
3120         /*
3121          * Now we're returning job status codes we just return a "" here. JRA.
3122          */
3123
3124         const char *p = "";
3125
3126 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3127         p = "unknown";
3128
3129         switch (queue->status) {
3130         case LPQ_QUEUED:
3131                 p = "Queued";
3132                 break;
3133         case LPQ_PAUSED:
3134                 p = "";    /* NT provides the paused string */
3135                 break;
3136         case LPQ_SPOOLING:
3137                 p = "Spooling";
3138                 break;
3139         case LPQ_PRINTING:
3140                 p = "Printing";
3141                 break;
3142         }
3143 #endif /* NO LONGER NEEDED. */
3144
3145         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3146 }
3147
3148 /*******************************************************************
3149  * fill a notify_info_data with job time
3150  ********************************************************************/
3151
3152 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3153                                     int snum,
3154                                     struct spoolss_Notify *data,
3155                                     print_queue_struct *queue,
3156                                     struct spoolss_PrinterInfo2 *pinfo2,
3157                                     TALLOC_CTX *mem_ctx)
3158 {
3159         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3160 }
3161
3162 /*******************************************************************
3163  * fill a notify_info_data with job size
3164  ********************************************************************/
3165
3166 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3167                                     int snum,
3168                                     struct spoolss_Notify *data,
3169                                     print_queue_struct *queue,
3170                                     struct spoolss_PrinterInfo2 *pinfo2,
3171                                     TALLOC_CTX *mem_ctx)
3172 {
3173         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3174 }
3175
3176 /*******************************************************************
3177  * fill a notify_info_data with page info
3178  ********************************************************************/
3179 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3180                                        int snum,
3181                                 struct spoolss_Notify *data,
3182                                 print_queue_struct *queue,
3183                                 struct spoolss_PrinterInfo2 *pinfo2,
3184                                 TALLOC_CTX *mem_ctx)
3185 {
3186         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3187 }
3188
3189 /*******************************************************************
3190  * fill a notify_info_data with pages printed info.
3191  ********************************************************************/
3192 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3193                                          int snum,
3194                                 struct spoolss_Notify *data,
3195                                 print_queue_struct *queue,
3196                                 struct spoolss_PrinterInfo2 *pinfo2,
3197                                 TALLOC_CTX *mem_ctx)
3198 {
3199         /* Add code when back-end tracks this */
3200         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3201 }
3202
3203 /*******************************************************************
3204  Fill a notify_info_data with job position.
3205  ********************************************************************/
3206
3207 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3208                                         int snum,
3209                                         struct spoolss_Notify *data,
3210                                         print_queue_struct *queue,
3211                                         struct spoolss_PrinterInfo2 *pinfo2,
3212                                         TALLOC_CTX *mem_ctx)
3213 {
3214         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3215 }
3216
3217 /*******************************************************************
3218  Fill a notify_info_data with submitted time.
3219  ********************************************************************/
3220
3221 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3222                                           int snum,
3223                                           struct spoolss_Notify *data,
3224                                           print_queue_struct *queue,
3225                                           struct spoolss_PrinterInfo2 *pinfo2,
3226                                           TALLOC_CTX *mem_ctx)
3227 {
3228         data->data.string.string = NULL;
3229         data->data.string.size = 0;
3230
3231         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3232                                &data->data.string.string,
3233                                &data->data.string.size);
3234
3235 }
3236
3237 struct s_notify_info_data_table
3238 {
3239         enum spoolss_NotifyType type;
3240         uint16_t field;
3241         const char *name;
3242         enum spoolss_NotifyTable variable_type;
3243         void (*fn) (struct messaging_context *msg_ctx,
3244                     int snum, struct spoolss_Notify *data,
3245                     print_queue_struct *queue,
3246                     struct spoolss_PrinterInfo2 *pinfo2,
3247                     TALLOC_CTX *mem_ctx);
3248 };
3249
3250 /* A table describing the various print notification constants and
3251    whether the notification data is a pointer to a variable sized
3252    buffer, a one value uint32_t or a two value uint32_t. */
3253
3254 static const struct s_notify_info_data_table notify_info_data_table[] =
3255 {
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3282 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3283 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3284 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3285 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3286 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3287 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3288 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3289 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3290 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3291 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3292 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3293 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3294 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3295 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3296 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3301 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3302 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3304 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3305 };
3306
3307 /*******************************************************************
3308  Return the variable_type of info_data structure.
3309 ********************************************************************/
3310
3311 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3312                                                                   uint16_t field)
3313 {
3314         int i=0;
3315
3316         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3317                 if ( (notify_info_data_table[i].type == type) &&
3318                      (notify_info_data_table[i].field == field) ) {
3319                         return notify_info_data_table[i].variable_type;
3320                 }
3321         }
3322
3323         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3324
3325         return (enum spoolss_NotifyTable) 0;
3326 }
3327
3328 /****************************************************************************
3329 ****************************************************************************/
3330
3331 static bool search_notify(enum spoolss_NotifyType type,
3332                           uint16_t field,
3333                           int *value)
3334 {
3335         int i;
3336
3337         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3338                 if (notify_info_data_table[i].type == type &&
3339                     notify_info_data_table[i].field == field &&
3340                     notify_info_data_table[i].fn != NULL) {
3341                         *value = i;
3342                         return true;
3343                 }
3344         }
3345
3346         return false;
3347 }
3348
3349 /****************************************************************************
3350 ****************************************************************************/
3351
3352 static void construct_info_data(struct spoolss_Notify *info_data,
3353                                 enum spoolss_NotifyType type,
3354                                 uint16_t field, int id)
3355 {
3356         info_data->type                 = type;
3357         info_data->field.field          = field;
3358         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3359         info_data->job_id               = id;
3360 }
3361
3362 /*******************************************************************
3363  *
3364  * fill a notify_info struct with info asked
3365  *
3366  ********************************************************************/
3367
3368 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3369                                           struct printer_handle *print_hnd,
3370                                           struct spoolss_NotifyInfo *info,
3371                                           struct spoolss_PrinterInfo2 *pinfo2,
3372                                           int snum,
3373                                           const struct spoolss_NotifyOptionType *option_type,
3374                                           uint32_t id,
3375                                           TALLOC_CTX *mem_ctx)
3376 {
3377         int field_num,j;
3378         enum spoolss_NotifyType type;
3379         uint16_t field;
3380
3381         struct spoolss_Notify *current_data;
3382
3383         type = option_type->type;
3384
3385         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3386                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3387                 option_type->count, lp_servicename(talloc_tos(), snum)));
3388
3389         for(field_num=0; field_num < option_type->count; field_num++) {
3390                 field = option_type->fields[field_num].field;
3391
3392                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3393
3394                 if (!search_notify(type, field, &j) )
3395                         continue;
3396
3397                 info->notifies = talloc_realloc(info, info->notifies,
3398                                                       struct spoolss_Notify,
3399                                                       info->count + 1);
3400                 if (info->notifies == NULL) {
3401                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3402                         return false;
3403                 }
3404
3405                 current_data = &info->notifies[info->count];
3406
3407                 construct_info_data(current_data, type, field, id);
3408
3409                 DEBUG(10, ("construct_notify_printer_info: "
3410                            "calling [%s]  snum=%d  printername=[%s])\n",
3411                            notify_info_data_table[j].name, snum,
3412                            pinfo2->printername));
3413
3414                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3415                                              NULL, pinfo2, mem_ctx);
3416
3417                 info->count++;
3418         }
3419
3420         return true;
3421 }
3422
3423 /*******************************************************************
3424  *
3425  * fill a notify_info struct with info asked
3426  *
3427  ********************************************************************/
3428
3429 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3430                                        print_queue_struct *queue,
3431                                        struct spoolss_NotifyInfo *info,
3432                                        struct spoolss_PrinterInfo2 *pinfo2,
3433                                        int snum,
3434                                        const struct spoolss_NotifyOptionType *option_type,
3435                                        uint32_t id,
3436                                        TALLOC_CTX *mem_ctx)
3437 {
3438         int field_num,j;
3439         enum spoolss_NotifyType type;
3440         uint16_t field;
3441         struct spoolss_Notify *current_data;
3442
3443         DEBUG(4,("construct_notify_jobs_info\n"));
3444
3445         type = option_type->type;
3446
3447         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3448                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3449                 option_type->count));
3450
3451         for(field_num=0; field_num<option_type->count; field_num++) {
3452                 field = option_type->fields[field_num].field;
3453
3454                 if (!search_notify(type, field, &j) )
3455                         continue;
3456
3457                 info->notifies = talloc_realloc(info, info->notifies,
3458                                                       struct spoolss_Notify,
3459                                                       info->count + 1);
3460                 if (info->notifies == NULL) {
3461                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3462                         return false;
3463                 }
3464
3465                 current_data=&(info->notifies[info->count]);
3466
3467                 construct_info_data(current_data, type, field, id);
3468                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3469                                              queue, pinfo2, mem_ctx);
3470                 info->count++;
3471         }
3472
3473         return true;
3474 }
3475
3476 /*
3477  * JFM: The enumeration is not that simple, it's even non obvious.
3478  *
3479  * let's take an example: I want to monitor the PRINTER SERVER for
3480  * the printer's name and the number of jobs currently queued.
3481  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3482  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3483  *
3484  * I have 3 printers on the back of my server.
3485  *
3486  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3487  * structures.
3488  *   Number     Data                    Id
3489  *      1       printer 1 name          1
3490  *      2       printer 1 cjob          1
3491  *      3       printer 2 name          2
3492  *      4       printer 2 cjob          2
3493  *      5       printer 3 name          3
3494  *      6       printer 3 name          3
3495  *
3496  * that's the print server case, the printer case is even worse.
3497  */
3498
3499 /*******************************************************************
3500  *
3501  * enumerate all printers on the printserver
3502  * fill a notify_info struct with info asked
3503  *
3504  ********************************************************************/
3505
3506 static WERROR printserver_notify_info(struct pipes_struct *p,
3507                                       struct policy_handle *hnd,
3508                                       struct spoolss_NotifyInfo *info,
3509                                       TALLOC_CTX *mem_ctx)
3510 {
3511         int snum;
3512         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3513         int n_services=lp_numservices();
3514         int i;
3515         struct spoolss_NotifyOption *option;
3516         struct spoolss_NotifyOptionType option_type;
3517         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3518         WERROR result;
3519
3520         DEBUG(4,("printserver_notify_info\n"));
3521
3522         if (!Printer)
3523                 return WERR_BADFID;
3524
3525         option = Printer->notify.option;
3526
3527         info->version   = 2;
3528         info->notifies  = NULL;
3529         info->count     = 0;
3530
3531         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3532            sending a ffpcn() request first */
3533
3534         if ( !option )
3535                 return WERR_BADFID;
3536
3537         for (i=0; i<option->count; i++) {
3538                 option_type = option->types[i];
3539
3540                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3541                         continue;
3542
3543                 for (snum = 0; snum < n_services; snum++) {
3544                         if (!lp_browseable(snum) ||
3545                             !lp_snum_ok(snum) ||
3546                             !lp_print_ok(snum)) {
3547                                 continue; /* skip */
3548                         }
3549
3550                         /* Maybe we should use the SYSTEM session_info here... */
3551                         result = winreg_get_printer_internal(mem_ctx,
3552                                                     get_session_info_system(),
3553                                                     p->msg_ctx,
3554                                                     lp_servicename(talloc_tos(), snum),
3555                                                     &pinfo2);
3556                         if (!W_ERROR_IS_OK(result)) {
3557                                 DEBUG(4, ("printserver_notify_info: "
3558                                           "Failed to get printer [%s]\n",
3559                                           lp_servicename(talloc_tos(), snum)));
3560                                 continue;
3561                         }
3562
3563
3564                         construct_notify_printer_info(p->msg_ctx,
3565                                                       Printer, info,
3566                                                       pinfo2, snum,
3567                                                       &option_type, snum,
3568                                                       mem_ctx);
3569
3570                         TALLOC_FREE(pinfo2);
3571                 }
3572         }
3573
3574 #if 0
3575         /*
3576          * Debugging information, don't delete.
3577          */
3578
3579         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3580         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3581         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3582
3583         for (i=0; i<info->count; i++) {
3584                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3585                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3586                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3587         }
3588 #endif
3589
3590         return WERR_OK;
3591 }
3592
3593 /*******************************************************************
3594  *
3595  * fill a notify_info struct with info asked
3596  *
3597  ********************************************************************/
3598
3599 static WERROR printer_notify_info(struct pipes_struct *p,
3600                                   struct policy_handle *hnd,
3601                                   struct spoolss_NotifyInfo *info,
3602                                   TALLOC_CTX *mem_ctx)
3603 {
3604         int snum;
3605         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3606         int i;
3607         uint32_t id;
3608         struct spoolss_NotifyOption *option;
3609         struct spoolss_NotifyOptionType option_type;
3610         int count,j;
3611         print_queue_struct *queue=NULL;
3612         print_status_struct status;
3613         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3614         WERROR result;
3615
3616         DEBUG(4,("printer_notify_info\n"));
3617
3618         if (!Printer)
3619                 return WERR_BADFID;
3620
3621         option = Printer->notify.option;
3622         id = 0x0;
3623
3624         info->version   = 2;
3625         info->notifies  = NULL;
3626         info->count     = 0;
3627
3628         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3629            sending a ffpcn() request first */
3630
3631         if ( !option )
3632                 return WERR_BADFID;
3633
3634         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3635                 return WERR_BADFID;
3636         }
3637
3638         /* Maybe we should use the SYSTEM session_info here... */
3639         result = winreg_get_printer_internal(mem_ctx,
3640                                     get_session_info_system(),
3641                                     p->msg_ctx,
3642                                     lp_servicename(talloc_tos(), snum), &pinfo2);
3643         if (!W_ERROR_IS_OK(result)) {
3644                 return WERR_BADFID;
3645         }
3646
3647         /*
3648          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3649          * correct servername.
3650          */
3651         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3652         if (pinfo2->servername == NULL) {
3653                 return WERR_NOMEM;
3654         }
3655
3656         for (i=0; i<option->count; i++) {
3657                 option_type = option->types[i];
3658
3659                 switch (option_type.type) {
3660                 case PRINTER_NOTIFY_TYPE:
3661                         if (construct_notify_printer_info(p->msg_ctx,
3662                                                           Printer, info,
3663                                                           pinfo2, snum,
3664                                                           &option_type, id,
3665                                                           mem_ctx)) {
3666                                 id--;
3667                         }
3668                         break;
3669
3670                 case JOB_NOTIFY_TYPE:
3671
3672                         count = print_queue_status(p->msg_ctx, snum, &queue,
3673                                                    &status);
3674
3675                         for (j=0; j<count; j++) {
3676                                 construct_notify_jobs_info(p->msg_ctx,
3677                                                            &queue[j], info,
3678                                                            pinfo2, snum,
3679                                                            &option_type,
3680                                                            queue[j].sysjob,
3681                                                            mem_ctx);
3682                         }
3683
3684                         SAFE_FREE(queue);
3685                         break;
3686                 }
3687         }
3688
3689         /*
3690          * Debugging information, don't delete.
3691          */
3692         /*
3693         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3694         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3695         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3696
3697         for (i=0; i<info->count; i++) {
3698                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3699                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3700                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3701         }
3702         */
3703
3704         talloc_free(pinfo2);
3705         return WERR_OK;
3706 }
3707
3708 /****************************************************************
3709  _spoolss_RouterRefreshPrinterChangeNotify
3710 ****************************************************************/
3711
3712 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3713                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3714 {
3715         struct spoolss_NotifyInfo *info;
3716
3717         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3718         WERROR result = WERR_BADFID;
3719
3720         /* we always have a spoolss_NotifyInfo struct */
3721         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3722         if (!info) {
3723                 result = WERR_NOMEM;
3724                 goto done;
3725         }
3726
3727         *r->out.info = info;
3728
3729         if (!Printer) {
3730                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3731                         "Invalid handle (%s:%u:%u).\n",
3732                         OUR_HANDLE(r->in.handle)));
3733                 goto done;
3734         }
3735
3736         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3737
3738         /*
3739          *      We are now using the change value, and
3740          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3741          *      I don't have a global notification system, I'm sending back all the
3742          *      information even when _NOTHING_ has changed.
3743          */
3744
3745         /* We need to keep track of the change value to send back in
3746            RRPCN replies otherwise our updates are ignored. */
3747
3748         Printer->notify.fnpcn = true;
3749
3750         if (Printer->notify.cli_chan != NULL &&
3751             Printer->notify.cli_chan->active_connections > 0) {
3752                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3753                         "Saving change value in request [%x]\n",
3754                         r->in.change_low));
3755                 Printer->notify.change = r->in.change_low;
3756         }
3757
3758         /* just ignore the spoolss_NotifyOption */
3759
3760         switch (Printer->printer_type) {
3761                 case SPLHND_SERVER:
3762                         result = printserver_notify_info(p, r->in.handle,
3763                                                          info, p->mem_ctx);
3764                         break;
3765
3766                 case SPLHND_PRINTER:
3767                         result = printer_notify_info(p, r->in.handle,
3768                                                      info, p->mem_ctx);
3769                         break;
3770         }
3771
3772         Printer->notify.fnpcn = false;
3773
3774 done:
3775         return result;
3776 }
3777
3778 /********************************************************************
3779  ********************************************************************/
3780
3781 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3782                                  const char *servername,
3783                                  const char *printername,
3784                                  const char **printername_p)
3785 {
3786         /* FIXME: add lp_force_printername() */
3787
3788         if (servername == NULL) {
3789                 *printername_p = talloc_strdup(mem_ctx, printername);
3790                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3791                 return WERR_OK;
3792         }
3793
3794         if (servername[0] == '\\' && servername[1] == '\\') {
3795                 servername += 2;
3796         }
3797
3798         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3799         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3800
3801         return WERR_OK;
3802 }
3803
3804 /********************************************************************
3805  ********************************************************************/
3806
3807 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3808                                           const char *printername)
3809 {
3810         if (dm == NULL) {
3811                 return;
3812         }
3813
3814         dm->devicename = talloc_strndup(dm, printername,
3815                                         MIN(strlen(printername), 31));
3816 }
3817
3818 /********************************************************************
3819  * construct_printer_info_0
3820  * fill a printer_info_0 struct
3821  ********************************************************************/
3822
3823 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3824                                       const struct auth_session_info *session_info,
3825                                       struct messaging_context *msg_ctx,
3826                                       struct spoolss_PrinterInfo2 *info2,
3827                                       const char *servername,
3828                                       struct spoolss_PrinterInfo0 *r,
3829                                       int snum)
3830 {
3831         int count;
3832         struct printer_session_counter *session_counter;
3833         struct timeval setuptime;
3834         print_status_struct status;
3835         WERROR result;
3836
3837         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3838         if (!W_ERROR_IS_OK(result)) {
3839                 return result;
3840         }
3841
3842         if (servername) {
3843                 r->servername = talloc_strdup(mem_ctx, servername);
3844                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3845         } else {
3846                 r->servername = NULL;
3847         }
3848
3849         count = print_queue_length(msg_ctx, snum, &status);
3850
3851         /* check if we already have a counter for this printer */
3852         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3853                 if (session_counter->snum == snum)
3854                         break;
3855         }
3856
3857         /* it's the first time, add it to the list */
3858         if (session_counter == NULL) {
3859                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3860                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3861                 session_counter->snum           = snum;
3862                 session_counter->counter        = 0;
3863                 DLIST_ADD(counter_list, session_counter);
3864         }
3865
3866         /* increment it */
3867         session_counter->counter++;
3868
3869         r->cjobs                        = count;
3870         r->total_jobs                   = 0;
3871         r->total_bytes                  = 0;
3872
3873         get_startup_time(&setuptime);
3874         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3875
3876         /* JFM:
3877          * the global_counter should be stored in a TDB as it's common to all the clients
3878          * and should be zeroed on samba startup
3879          */
3880         r->global_counter               = session_counter->counter;
3881         r->total_pages                  = 0;
3882         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3883         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3884         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3885         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3886         r->spooling                     = 0;
3887         r->max_spooling                 = 0;
3888         r->session_counter              = session_counter->counter;
3889         r->num_error_out_of_paper       = 0x0;
3890         r->num_error_not_ready          = 0x0;          /* number of print failure */
3891         r->job_error                    = 0x0;
3892         r->number_of_processors         = 0x1;
3893         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3894         r->high_part_total_bytes        = 0x0;
3895
3896         /* ChangeID in milliseconds*/
3897         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3898                                     info2->sharename, &r->change_id);
3899
3900         r->last_error                   = WERR_OK;
3901         r->status                       = nt_printq_status(status.status);
3902         r->enumerate_network_printers   = 0x0;
3903         r->c_setprinter                 = 0x0;
3904         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3905         r->processor_level              = 0x6;          /* 6  ???*/
3906         r->ref_ic                       = 0;
3907         r->reserved2                    = 0;
3908         r->reserved3                    = 0;
3909
3910         return WERR_OK;
3911 }
3912
3913
3914 /********************************************************************
3915  * construct_printer_info1
3916  * fill a spoolss_PrinterInfo1 struct
3917 ********************************************************************/
3918
3919 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3920                                       const struct spoolss_PrinterInfo2 *info2,
3921                                       uint32_t flags,
3922                                       const char *servername,
3923                                       struct spoolss_PrinterInfo1 *r,
3924                                       int snum)
3925 {
3926         WERROR result;
3927
3928         r->flags                = flags;
3929
3930         if (info2->comment == NULL || info2->comment[0] == '\0') {
3931                 r->comment      = lp_comment(mem_ctx, snum);
3932         } else {
3933                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3934         }
3935         W_ERROR_HAVE_NO_MEMORY(r->comment);
3936
3937         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3938         if (!W_ERROR_IS_OK(result)) {
3939                 return result;
3940         }
3941
3942         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3943                                                   r->name,
3944                                                   info2->drivername,
3945                                                   r->comment);
3946         W_ERROR_HAVE_NO_MEMORY(r->description);
3947
3948         return WERR_OK;
3949 }
3950
3951 /********************************************************************
3952  * construct_printer_info2
3953  * fill a spoolss_PrinterInfo2 struct
3954 ********************************************************************/
3955
3956 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3957                                       struct messaging_context *msg_ctx,
3958                                       const struct spoolss_PrinterInfo2 *info2,
3959                                       const char *servername,
3960                                       struct spoolss_PrinterInfo2 *r,
3961                                       int snum)
3962 {
3963         int count;
3964         print_status_struct status;
3965         WERROR result;
3966
3967         count = print_queue_length(msg_ctx, snum, &status);
3968
3969         if (servername) {
3970                 r->servername           = talloc_strdup(mem_ctx, servername);
3971                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3972         } else {
3973                 r->servername           = NULL;
3974         }
3975
3976         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3977         if (!W_ERROR_IS_OK(result)) {
3978                 return result;
3979         }
3980
3981         r->sharename            = lp_servicename(mem_ctx, snum);
3982         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3983         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3984         W_ERROR_HAVE_NO_MEMORY(r->portname);
3985         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3986         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3987
3988         if (info2->comment[0] == '\0') {
3989                 r->comment      = lp_comment(mem_ctx, snum);
3990         } else {
3991                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
3992         }
3993         W_ERROR_HAVE_NO_MEMORY(r->comment);
3994
3995         r->location     = talloc_strdup(mem_ctx, info2->location);
3996         if (info2->location[0] == '\0') {
3997                 const char *loc = NULL;
3998                 NTSTATUS nt_status;
3999
4000                 nt_status = printer_list_get_printer(mem_ctx,
4001                                                      info2->sharename,
4002                                                      NULL,
4003                                                      &loc,
4004                                                      NULL);
4005                 if (NT_STATUS_IS_OK(nt_status)) {
4006                         if (loc != NULL) {
4007                                 r->location = talloc_strdup(mem_ctx, loc);
4008                         }
4009                 }
4010         }
4011         W_ERROR_HAVE_NO_MEMORY(r->location);
4012
4013         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4014         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4015         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4016         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4017         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4018         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4019         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4020         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4021
4022         r->attributes           = info2->attributes;
4023
4024         r->priority             = info2->priority;
4025         r->defaultpriority      = info2->defaultpriority;
4026         r->starttime            = info2->starttime;
4027         r->untiltime            = info2->untiltime;
4028         r->status               = nt_printq_status(status.status);
4029         r->cjobs                = count;
4030         r->averageppm           = info2->averageppm;
4031
4032         if (info2->devmode != NULL) {
4033                 result = copy_devicemode(mem_ctx,
4034                                          info2->devmode,
4035                                          &r->devmode);
4036                 if (!W_ERROR_IS_OK(result)) {
4037                         return result;
4038                 }
4039         } else if (lp_default_devmode(snum)) {
4040                 result = spoolss_create_default_devmode(mem_ctx,
4041                                                         info2->printername,
4042                                                         &r->devmode);
4043                 if (!W_ERROR_IS_OK(result)) {
4044                         return result;
4045                 }
4046         } else {
4047                 r->devmode = NULL;
4048                 DEBUG(8,("Returning NULL Devicemode!\n"));
4049         }
4050
4051         compose_devicemode_devicename(r->devmode, r->printername);
4052
4053         r->secdesc = NULL;
4054
4055         if (info2->secdesc != NULL) {
4056                 /* don't use talloc_steal() here unless you do a deep steal of all
4057                    the SEC_DESC members */
4058
4059                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4060         }
4061
4062         return WERR_OK;
4063 }
4064
4065 /********************************************************************
4066  * construct_printer_info3
4067  * fill a spoolss_PrinterInfo3 struct
4068  ********************************************************************/
4069
4070 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4071                                       const struct spoolss_PrinterInfo2 *info2,
4072                                       const char *servername,
4073                                       struct spoolss_PrinterInfo3 *r,
4074                                       int snum)
4075 {
4076         /* These are the components of the SD we are returning. */
4077
4078         if (info2->secdesc != NULL) {
4079                 /* don't use talloc_steal() here unless you do a deep steal of all
4080                    the SEC_DESC members */
4081
4082                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4083                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4084         }
4085
4086         return WERR_OK;
4087 }
4088
4089 /********************************************************************
4090  * construct_printer_info4
4091  * fill a spoolss_PrinterInfo4 struct
4092  ********************************************************************/
4093
4094 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4095                                       const struct spoolss_PrinterInfo2 *info2,
4096                                       const char *servername,
4097                                       struct spoolss_PrinterInfo4 *r,
4098                                       int snum)
4099 {
4100         WERROR result;
4101
4102         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4103         if (!W_ERROR_IS_OK(result)) {
4104                 return result;
4105         }
4106
4107         if (servername) {
4108                 r->servername   = talloc_strdup(mem_ctx, servername);
4109                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4110         } else {
4111                 r->servername = NULL;
4112         }
4113
4114         r->attributes   = info2->attributes;
4115
4116         return WERR_OK;
4117 }
4118
4119 /********************************************************************
4120  * construct_printer_info5
4121  * fill a spoolss_PrinterInfo5 struct
4122  ********************************************************************/
4123
4124 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4125                                       const struct spoolss_PrinterInfo2 *info2,
4126                                       const char *servername,
4127                                       struct spoolss_PrinterInfo5 *r,
4128                                       int snum)
4129 {
4130         WERROR result;
4131
4132         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4133         if (!W_ERROR_IS_OK(result)) {
4134                 return result;
4135         }
4136
4137         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4138         W_ERROR_HAVE_NO_MEMORY(r->portname);
4139
4140         r->attributes   = info2->attributes;
4141
4142         /* these two are not used by NT+ according to MSDN */
4143         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4144         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4145
4146         return WERR_OK;
4147 }
4148
4149 /********************************************************************
4150  * construct_printer_info_6
4151  * fill a spoolss_PrinterInfo6 struct
4152  ********************************************************************/
4153
4154 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4155                                       struct messaging_context *msg_ctx,
4156                                       const struct spoolss_PrinterInfo2 *info2,
4157                                       const char *servername,
4158                                       struct spoolss_PrinterInfo6 *r,
4159                                       int snum)
4160 {
4161         print_status_struct status;
4162
4163         print_queue_length(msg_ctx, snum, &status);
4164
4165         r->status = nt_printq_status(status.status);
4166
4167         return WERR_OK;
4168 }
4169
4170 /********************************************************************
4171  * construct_printer_info7
4172  * fill a spoolss_PrinterInfo7 struct
4173  ********************************************************************/
4174
4175 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4176                                       struct messaging_context *msg_ctx,
4177                                       const char *servername,
4178                                       struct spoolss_PrinterInfo7 *r,
4179                                       int snum)
4180 {
4181         const struct auth_session_info *session_info;
4182         char *printer;
4183         WERROR werr;
4184         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4185         if (tmp_ctx == NULL) {
4186                 return WERR_NOMEM;
4187         }
4188
4189         session_info = get_session_info_system();
4190         SMB_ASSERT(session_info != NULL);
4191
4192         printer = lp_servicename(tmp_ctx, snum);
4193         if (printer == NULL) {
4194                 DEBUG(0, ("invalid printer snum %d\n", snum));
4195                 werr = WERR_INVALID_PARAM;
4196                 goto out_tmp_free;
4197         }
4198
4199         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4200                                  servername, printer, NULL)) {
4201                 struct GUID guid;
4202                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4203                                            printer, &guid);
4204                 if (!W_ERROR_IS_OK(werr)) {
4205                         goto out_tmp_free;
4206                 }
4207                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4208                 r->action = DSPRINT_PUBLISH;
4209         } else {
4210                 r->guid = talloc_strdup(mem_ctx, "");
4211                 r->action = DSPRINT_UNPUBLISH;
4212         }
4213         if (r->guid == NULL) {
4214                 werr = WERR_NOMEM;
4215                 goto out_tmp_free;
4216         }
4217
4218         werr = WERR_OK;
4219 out_tmp_free:
4220         talloc_free(tmp_ctx);
4221         return werr;
4222 }
4223
4224 /********************************************************************
4225  * construct_printer_info8
4226  * fill a spoolss_PrinterInfo8 struct
4227  ********************************************************************/
4228
4229 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4230                                       const struct spoolss_PrinterInfo2 *info2,
4231                                       const char *servername,
4232                                       struct spoolss_DeviceModeInfo *r,
4233                                       int snum)
4234 {
4235         WERROR result;
4236         const char *printername;
4237
4238         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4239         if (!W_ERROR_IS_OK(result)) {
4240                 return result;
4241         }
4242
4243         if (info2->devmode != NULL) {
4244                 result = copy_devicemode(mem_ctx,
4245                                          info2->devmode,
4246                                          &r->devmode);
4247                 if (!W_ERROR_IS_OK(result)) {
4248                         return result;
4249                 }
4250         } else if (lp_default_devmode(snum)) {
4251                 result = spoolss_create_default_devmode(mem_ctx,
4252                                                         info2->printername,
4253                                                         &r->devmode);
4254                 if (!W_ERROR_IS_OK(result)) {
4255                         return result;
4256                 }
4257         } else {
4258                 r->devmode = NULL;
4259                 DEBUG(8,("Returning NULL Devicemode!\n"));
4260         }
4261
4262         compose_devicemode_devicename(r->devmode, printername);
4263
4264         return WERR_OK;
4265 }
4266
4267
4268 /********************************************************************
4269 ********************************************************************/
4270
4271 static bool snum_is_shared_printer(int snum)
4272 {
4273         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4274 }
4275
4276 /********************************************************************
4277  Spoolss_enumprinters.
4278 ********************************************************************/
4279
4280 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4281                                            const struct auth_session_info *session_info,
4282                                            struct messaging_context *msg_ctx,
4283                                            const char *servername,
4284                                            uint32_t level,
4285                                            uint32_t flags,
4286                                            union spoolss_PrinterInfo **info_p,
4287                                            uint32_t *count_p)
4288 {
4289         int snum;
4290         int n_services = lp_numservices();
4291         union spoolss_PrinterInfo *info = NULL;
4292         uint32_t count = 0;
4293         WERROR result = WERR_OK;
4294         struct dcerpc_binding_handle *b = NULL;
4295         TALLOC_CTX *tmp_ctx = NULL;
4296
4297         tmp_ctx = talloc_new(mem_ctx);
4298         if (!tmp_ctx) {
4299                 return WERR_NOMEM;
4300         }
4301
4302         *count_p = 0;
4303         *info_p = NULL;
4304
4305         for (snum = 0; snum < n_services; snum++) {
4306
4307                 const char *printer;
4308                 struct spoolss_PrinterInfo2 *info2;
4309
4310                 if (!snum_is_shared_printer(snum)) {
4311                         continue;
4312                 }
4313
4314                 printer = lp_const_servicename(snum);
4315
4316                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4317                         printer, snum));
4318
4319                 if (b == NULL) {
4320                         result = winreg_printer_binding_handle(tmp_ctx,
4321                                                                session_info,
4322                                                                msg_ctx,
4323                                                                &b);
4324                         if (!W_ERROR_IS_OK(result)) {
4325                                 goto out;
4326                         }
4327                 }
4328
4329                 result = winreg_create_printer(tmp_ctx, b,
4330                                                printer);
4331                 if (!W_ERROR_IS_OK(result)) {
4332                         goto out;
4333                 }
4334
4335                 info = talloc_realloc(tmp_ctx, info,
4336                                             union spoolss_PrinterInfo,
4337                                             count + 1);
4338                 if (!info) {
4339                         result = WERR_NOMEM;
4340                         goto out;
4341                 }
4342
4343                 result = winreg_get_printer(tmp_ctx, b,
4344                                             printer, &info2);
4345                 if (!W_ERROR_IS_OK(result)) {
4346                         goto out;
4347                 }
4348
4349                 switch (level) {
4350                 case 0:
4351                         result = construct_printer_info0(info, session_info,
4352                                                          msg_ctx, info2,
4353                                                          servername,
4354                                                          &info[count].info0, snum);
4355                         break;
4356                 case 1:
4357                         result = construct_printer_info1(info, info2, flags,
4358                                                          servername,
4359                                                          &info[count].info1, snum);
4360                         break;
4361                 case 2:
4362                         result = construct_printer_info2(info, msg_ctx, info2,
4363                                                          servername,
4364                                                          &info[count].info2, snum);
4365                         break;
4366                 case 4:
4367                         result = construct_printer_info4(info, info2,
4368                                                          servername,
4369                                                          &info[count].info4, snum);
4370                         break;
4371                 case 5:
4372                         result = construct_printer_info5(info, info2,
4373                                                          servername,
4374                                                          &info[count].info5, snum);
4375                         break;
4376
4377                 default:
4378                         result = WERR_UNKNOWN_LEVEL;
4379                         goto out;
4380                 }
4381
4382                 if (!W_ERROR_IS_OK(result)) {
4383                         goto out;
4384                 }
4385
4386                 count++;
4387         }
4388
4389 out:
4390         if (W_ERROR_IS_OK(result)) {
4391                 *info_p = talloc_move(mem_ctx, &info);
4392                 *count_p = count;
4393         }
4394
4395         talloc_free(tmp_ctx);
4396
4397         return result;
4398 }
4399
4400 /********************************************************************
4401  * handle enumeration of printers at level 0
4402  ********************************************************************/
4403
4404 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4405                                   const struct auth_session_info *session_info,
4406                                   struct messaging_context *msg_ctx,
4407                                   uint32_t flags,
4408                                   const char *servername,
4409                                   union spoolss_PrinterInfo **info,
4410                                   uint32_t *count)
4411 {
4412         DEBUG(4,("enum_all_printers_info_0\n"));
4413
4414         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4415                                             servername, 0, flags, info, count);
4416 }
4417
4418
4419 /********************************************************************
4420 ********************************************************************/
4421
4422 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4423                                        const struct auth_session_info *session_info,
4424                                        struct messaging_context *msg_ctx,
4425                                        const char *servername,
4426                                        uint32_t flags,
4427                                        union spoolss_PrinterInfo **info,
4428                                        uint32_t *count)
4429 {
4430         DEBUG(4,("enum_all_printers_info_1\n"));
4431
4432         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4433                                             servername, 1, flags, info, count);
4434 }
4435
4436 /********************************************************************
4437  enum_all_printers_info_1_local.
4438 *********************************************************************/
4439
4440 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4441                                              const struct auth_session_info *session_info,
4442                                              struct messaging_context *msg_ctx,
4443                                              const char *servername,
4444                                              union spoolss_PrinterInfo **info,
4445                                              uint32_t *count)
4446 {
4447         DEBUG(4,("enum_all_printers_info_1_local\n"));
4448
4449         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4450                                         servername, PRINTER_ENUM_ICON8, info, count);
4451 }
4452
4453 /********************************************************************
4454  enum_all_printers_info_1_name.
4455 *********************************************************************/
4456
4457 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4458                                             const struct auth_session_info *session_info,
4459                                             struct messaging_context *msg_ctx,
4460                                             const char *servername,
4461                                             union spoolss_PrinterInfo **info,
4462                                             uint32_t *count)
4463 {
4464         const char *s = servername;
4465
4466         DEBUG(4,("enum_all_printers_info_1_name\n"));
4467
4468         if (servername != NULL &&
4469             (servername[0] == '\\') && (servername[1] == '\\')) {
4470                 s = servername + 2;
4471         }
4472
4473         if (!is_myname_or_ipaddr(s)) {
4474                 return WERR_INVALID_NAME;
4475         }
4476
4477         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4478                                         servername, PRINTER_ENUM_ICON8, info, count);
4479 }
4480
4481 /********************************************************************
4482  enum_all_printers_info_1_network.
4483 *********************************************************************/
4484
4485 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4486                                                const struct auth_session_info *session_info,
4487                                                struct messaging_context *msg_ctx,
4488                                                const char *servername,
4489                                                union spoolss_PrinterInfo **info,
4490                                                uint32_t *count)
4491 {
4492         const char *s = servername;
4493
4494         DEBUG(4,("enum_all_printers_info_1_network\n"));
4495
4496         /* If we respond to a enum_printers level 1 on our name with flags
4497            set to PRINTER_ENUM_REMOTE with a list of printers then these
4498            printers incorrectly appear in the APW browse list.
4499            Specifically the printers for the server appear at the workgroup
4500            level where all the other servers in the domain are
4501            listed. Windows responds to this call with a
4502            WERR_CAN_NOT_COMPLETE so we should do the same. */
4503
4504         if (servername != NULL &&
4505             (servername[0] == '\\') && (servername[1] == '\\')) {
4506                  s = servername + 2;
4507         }
4508
4509         if (is_myname_or_ipaddr(s)) {
4510                  return WERR_CAN_NOT_COMPLETE;
4511         }
4512
4513         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4514                                         servername, PRINTER_ENUM_NAME, info, count);
4515 }
4516
4517 /********************************************************************
4518  * api_spoolss_enumprinters
4519  *
4520  * called from api_spoolss_enumprinters (see this to understand)
4521  ********************************************************************/
4522
4523 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4524                                        const struct auth_session_info *session_info,
4525                                        struct messaging_context *msg_ctx,
4526                                        const char *servername,
4527                                        union spoolss_PrinterInfo **info,
4528                                        uint32_t *count)
4529 {
4530         DEBUG(4,("enum_all_printers_info_2\n"));
4531
4532         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4533                                             servername, 2, 0, info, count);
4534 }
4535
4536 /********************************************************************
4537  * handle enumeration of printers at level 1
4538  ********************************************************************/
4539
4540 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4541                                   const struct auth_session_info *session_info,
4542                                   struct messaging_context *msg_ctx,
4543                                   uint32_t flags,
4544                                   const char *servername,
4545                                   union spoolss_PrinterInfo **info,
4546                                   uint32_t *count)
4547 {
4548         /* Not all the flags are equals */
4549
4550         if (flags & PRINTER_ENUM_LOCAL) {
4551                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4552                                                       msg_ctx, servername, info, count);
4553         }
4554
4555         if (flags & PRINTER_ENUM_NAME) {
4556                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4557                                                      msg_ctx, servername, info,
4558                                                      count);
4559         }
4560
4561         if (flags & PRINTER_ENUM_NETWORK) {
4562                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4563                                                         msg_ctx, servername, info,
4564                                                         count);
4565         }
4566
4567         return WERR_OK; /* NT4sp5 does that */
4568 }
4569
4570 /********************************************************************
4571  * handle enumeration of printers at level 2
4572  ********************************************************************/
4573
4574 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4575                                   const struct auth_session_info *session_info,
4576                                   struct messaging_context *msg_ctx,
4577                                   uint32_t flags,
4578                                   const char *servername,
4579                                   union spoolss_PrinterInfo **info,
4580                                   uint32_t *count)
4581 {
4582         if (flags & PRINTER_ENUM_LOCAL) {
4583
4584                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4585                                                 servername,
4586                                                 info, count);
4587         }
4588
4589         if (flags & PRINTER_ENUM_NAME) {
4590                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4591                         return WERR_INVALID_NAME;
4592                 }
4593
4594                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4595                                                 servername,
4596                                                 info, count);
4597         }
4598
4599         if (flags & PRINTER_ENUM_REMOTE) {
4600                 return WERR_UNKNOWN_LEVEL;
4601         }
4602
4603         return WERR_OK;
4604 }
4605
4606 /********************************************************************
4607  * handle enumeration of printers at level 4
4608  ********************************************************************/
4609
4610 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4611                                   const struct auth_session_info *session_info,
4612                                   struct messaging_context *msg_ctx,
4613                                   uint32_t flags,
4614                                   const char *servername,
4615                                   union spoolss_PrinterInfo **info,
4616                                   uint32_t *count)
4617 {
4618         DEBUG(4,("enum_all_printers_info_4\n"));
4619
4620         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4621                                             servername, 4, flags, info, count);
4622 }
4623
4624
4625 /********************************************************************
4626  * handle enumeration of printers at level 5
4627  ********************************************************************/
4628
4629 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4630                                   const struct auth_session_info *session_info,
4631                                   struct messaging_context *msg_ctx,
4632                                   uint32_t flags,
4633                                   const char *servername,
4634                                   union spoolss_PrinterInfo **info,
4635                                   uint32_t *count)
4636 {
4637         DEBUG(4,("enum_all_printers_info_5\n"));
4638
4639         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4640                                             servername, 5, flags, info, count);
4641 }
4642
4643 /****************************************************************
4644  _spoolss_EnumPrinters
4645 ****************************************************************/
4646
4647 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4648                              struct spoolss_EnumPrinters *r)
4649 {
4650         const struct auth_session_info *session_info = get_session_info_system();
4651         WERROR result;
4652
4653         /* that's an [in out] buffer */
4654
4655         if (!r->in.buffer && (r->in.offered != 0)) {
4656                 return WERR_INVALID_PARAM;
4657         }
4658
4659         DEBUG(4,("_spoolss_EnumPrinters\n"));
4660
4661         *r->out.needed = 0;
4662         *r->out.count = 0;
4663         *r->out.info = NULL;
4664
4665         /*
4666          * Level 1:
4667          *          flags==PRINTER_ENUM_NAME
4668          *           if name=="" then enumerates all printers
4669          *           if name!="" then enumerate the printer
4670          *          flags==PRINTER_ENUM_REMOTE
4671          *          name is NULL, enumerate printers
4672          * Level 2: name!="" enumerates printers, name can't be NULL
4673          * Level 3: doesn't exist
4674          * Level 4: does a local registry lookup
4675          * Level 5: same as Level 2
4676          */
4677
4678         if (r->in.server && r->in.server[0] == '\0') {
4679                 r->in.server = NULL;
4680         }
4681
4682         switch (r->in.level) {
4683         case 0:
4684                 result = enumprinters_level0(p->mem_ctx, session_info,
4685                                              p->msg_ctx, r->in.flags,
4686                                              r->in.server,
4687                                              r->out.info, r->out.count);
4688                 break;
4689         case 1:
4690                 result = enumprinters_level1(p->mem_ctx, session_info,
4691                                              p->msg_ctx, r->in.flags,
4692                                              r->in.server,
4693                                              r->out.info, r->out.count);
4694                 break;
4695         case 2:
4696                 result = enumprinters_level2(p->mem_ctx, session_info,
4697                                              p->msg_ctx, r->in.flags,
4698                                              r->in.server,
4699                                              r->out.info, r->out.count);
4700                 break;
4701         case 4:
4702                 result = enumprinters_level4(p->mem_ctx, session_info,
4703                                              p->msg_ctx, r->in.flags,
4704                                              r->in.server,
4705                                              r->out.info, r->out.count);
4706                 break;
4707         case 5:
4708                 result = enumprinters_level5(p->mem_ctx, session_info,
4709                                              p->msg_ctx, r->in.flags,
4710                                              r->in.server,
4711                                              r->out.info, r->out.count);
4712                 break;
4713         default:
4714                 return WERR_UNKNOWN_LEVEL;
4715         }
4716
4717         if (!W_ERROR_IS_OK(result)) {
4718                 return result;
4719         }
4720
4721         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4722                                                      spoolss_EnumPrinters,
4723                                                      *r->out.info, r->in.level,
4724                                                      *r->out.count);
4725         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4726         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4727
4728         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4729 }
4730
4731 /****************************************************************
4732  _spoolss_GetPrinter
4733 ****************************************************************/
4734
4735 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4736                            struct spoolss_GetPrinter *r)
4737 {
4738         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4739         struct spoolss_PrinterInfo2 *info2 = NULL;
4740         WERROR result = WERR_OK;
4741         int snum;
4742
4743         /* that's an [in out] buffer */
4744
4745         if (!r->in.buffer && (r->in.offered != 0)) {
4746                 return WERR_INVALID_PARAM;
4747         }
4748
4749         *r->out.needed = 0;
4750
4751         if (Printer == NULL) {
4752                 return WERR_BADFID;
4753         }
4754
4755         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4756                 return WERR_BADFID;
4757         }
4758
4759         result = winreg_get_printer_internal(p->mem_ctx,
4760                                     get_session_info_system(),
4761                                     p->msg_ctx,
4762                                     lp_const_servicename(snum),
4763                                     &info2);
4764         if (!W_ERROR_IS_OK(result)) {
4765                 goto out;
4766         }
4767
4768         switch (r->in.level) {
4769         case 0:
4770                 result = construct_printer_info0(p->mem_ctx,
4771                                                  get_session_info_system(),
4772                                                  p->msg_ctx,
4773                                                  info2,
4774                                                  Printer->servername,
4775                                                  &r->out.info->info0,
4776                                                  snum);
4777                 break;
4778         case 1:
4779                 result = construct_printer_info1(p->mem_ctx, info2,
4780                                                  PRINTER_ENUM_ICON8,
4781                                                  Printer->servername,
4782                                                  &r->out.info->info1, snum);
4783                 break;
4784         case 2:
4785                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4786                                                  Printer->servername,
4787                                                  &r->out.info->info2, snum);
4788                 break;
4789         case 3:
4790                 result = construct_printer_info3(p->mem_ctx, info2,
4791                                                  Printer->servername,
4792                                                  &r->out.info->info3, snum);
4793                 break;
4794         case 4:
4795                 result = construct_printer_info4(p->mem_ctx, info2,
4796                                                  Printer->servername,
4797                                                  &r->out.info->info4, snum);
4798                 break;
4799         case 5:
4800                 result = construct_printer_info5(p->mem_ctx, info2,
4801                                                  Printer->servername,
4802                                                  &r->out.info->info5, snum);
4803                 break;
4804         case 6:
4805                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4806                                                  Printer->servername,
4807                                                  &r->out.info->info6, snum);
4808                 break;
4809         case 7:
4810                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4811                                                  Printer->servername,
4812                                                  &r->out.info->info7, snum);
4813                 break;
4814         case 8:
4815                 result = construct_printer_info8(p->mem_ctx, info2,
4816                                                  Printer->servername,
4817                                                  &r->out.info->info8, snum);
4818                 break;
4819         default:
4820                 result = WERR_UNKNOWN_LEVEL;
4821                 break;
4822         }
4823         TALLOC_FREE(info2);
4824
4825  out:
4826         if (!W_ERROR_IS_OK(result)) {
4827                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4828                           r->in.level, win_errstr(result)));
4829                 TALLOC_FREE(r->out.info);
4830                 return result;
4831         }
4832
4833         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4834                                                r->out.info, r->in.level);
4835         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4836
4837         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4838 }
4839
4840 /********************************************************************
4841  ********************************************************************/
4842
4843 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4844         do { \
4845                 if (in && strlen(in)) { \
4846                         out = talloc_strdup(mem_ctx, in); \
4847                 } else { \
4848                         out = talloc_strdup(mem_ctx, ""); \
4849                 } \
4850                 W_ERROR_HAVE_NO_MEMORY(out); \
4851         } while (0);
4852
4853 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4854         do { \
4855                 if (in && strlen(in)) { \
4856                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4857                 } else { \
4858                         out = talloc_strdup(mem_ctx, ""); \
4859                 } \
4860                 W_ERROR_HAVE_NO_MEMORY(out); \
4861         } while (0);
4862
4863 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4864                                                   const char **string_array,
4865                                                   const char ***presult,
4866                                                   const char *cservername,
4867                                                   const char *arch,
4868                                                   int version)
4869 {
4870         int i, num_strings = 0;
4871         const char **array = NULL;
4872
4873         if (string_array == NULL) {
4874                 return WERR_INVALID_PARAMETER;
4875         }
4876
4877         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4878                 const char *str = NULL;
4879
4880                 if (cservername == NULL || arch == NULL) {
4881                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4882                 } else {
4883                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4884                 }
4885
4886                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4887                         TALLOC_FREE(array);
4888                         return WERR_NOMEM;
4889                 }
4890         }
4891
4892         if (i > 0) {
4893                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4894                              &array, &num_strings);
4895         }
4896
4897         if (presult != NULL) {
4898                 *presult = array;
4899         } else {
4900                 talloc_free(array);
4901         }
4902
4903         return WERR_OK;
4904 }
4905
4906 /********************************************************************
4907  * fill a spoolss_DriverInfo1 struct
4908  ********************************************************************/
4909
4910 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4911                                         struct spoolss_DriverInfo1 *r,
4912                                         const struct spoolss_DriverInfo8 *driver,
4913                                         const char *servername)
4914 {
4915         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4916         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4917
4918         return WERR_OK;
4919 }
4920
4921 /********************************************************************
4922  * fill a spoolss_DriverInfo2 struct
4923  ********************************************************************/
4924
4925 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4926                                         struct spoolss_DriverInfo2 *r,
4927                                         const struct spoolss_DriverInfo8 *driver,
4928                                         const char *servername)
4929
4930 {
4931         const char *cservername = canon_servername(servername);
4932
4933         r->version              = driver->version;
4934
4935         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4936         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4937         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4938         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4939
4940         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4941                                driver->architecture,
4942                                driver->version,
4943                                driver->driver_path,
4944                                r->driver_path);
4945
4946         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4947                                driver->architecture,
4948                                driver->version,
4949                                driver->data_file,
4950                                r->data_file);
4951
4952         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4953                                driver->architecture,
4954                                driver->version,
4955                                driver->config_file,
4956                                r->config_file);
4957
4958         return WERR_OK;
4959 }
4960
4961 /********************************************************************
4962  * fill a spoolss_DriverInfo3 struct
4963  ********************************************************************/
4964
4965 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4966                                         struct spoolss_DriverInfo3 *r,
4967                                         const struct spoolss_DriverInfo8 *driver,
4968                                         const char *servername)
4969 {
4970         const char *cservername = canon_servername(servername);
4971
4972         r->version              = driver->version;
4973
4974         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4975         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4976         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4977         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4978
4979         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4980                                driver->architecture,
4981                                driver->version,
4982                                driver->driver_path,
4983                                r->driver_path);
4984
4985         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4986                                driver->architecture,
4987                                driver->version,
4988                                driver->data_file,
4989                                r->data_file);
4990
4991         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4992                                driver->architecture,
4993                                driver->version,
4994                                driver->config_file,
4995                                r->config_file);
4996
4997         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4998                                driver->architecture,
4999                                driver->version,
5000                                driver->help_file,
5001                                r->help_file);
5002
5003         FILL_DRIVER_STRING(mem_ctx,
5004                            driver->monitor_name,
5005                            r->monitor_name);
5006
5007         FILL_DRIVER_STRING(mem_ctx,
5008                            driver->default_datatype,
5009                            r->default_datatype);
5010
5011         return string_array_from_driver_info(mem_ctx,
5012                                              driver->dependent_files,
5013                                              &r->dependent_files,
5014                                              cservername,
5015                                              driver->architecture,
5016                                              driver->version);
5017 }
5018
5019 /********************************************************************
5020  * fill a spoolss_DriverInfo4 struct
5021  ********************************************************************/
5022
5023 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5024                                         struct spoolss_DriverInfo4 *r,
5025                                         const struct spoolss_DriverInfo8 *driver,
5026                                         const char *servername)
5027 {
5028         const char *cservername = canon_servername(servername);
5029         WERROR result;
5030
5031         r->version              = driver->version;
5032
5033         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5034         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5035         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5036         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5037
5038         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5039                                driver->architecture,
5040                                driver->version,
5041                                driver->driver_path,
5042                                r->driver_path);
5043
5044         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5045                                driver->architecture,
5046                                driver->version,
5047                                driver->data_file,
5048                                r->data_file);
5049
5050         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5051                                driver->architecture,
5052                                driver->version,
5053                                driver->config_file,
5054                                r->config_file);
5055
5056         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5057                                driver->architecture,
5058                                driver->version,
5059                                driver->help_file,
5060                                r->help_file);
5061
5062         result = string_array_from_driver_info(mem_ctx,
5063                                                driver->dependent_files,
5064                                                &r->dependent_files,
5065                                                cservername,
5066                                                driver->architecture,
5067                                                driver->version);
5068         if (!W_ERROR_IS_OK(result)) {
5069                 return result;
5070         }
5071
5072         FILL_DRIVER_STRING(mem_ctx,
5073                            driver->monitor_name,
5074                            r->monitor_name);
5075
5076         FILL_DRIVER_STRING(mem_ctx,
5077                            driver->default_datatype,
5078                            r->default_datatype);
5079
5080
5081         result = string_array_from_driver_info(mem_ctx,
5082                                                driver->previous_names,
5083                                                &r->previous_names,
5084                                                NULL, NULL, 0);
5085
5086         return result;
5087 }
5088
5089 /********************************************************************
5090  * fill a spoolss_DriverInfo5 struct
5091  ********************************************************************/
5092
5093 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5094                                         struct spoolss_DriverInfo5 *r,
5095                                         const struct spoolss_DriverInfo8 *driver,
5096                                         const char *servername)
5097 {
5098         const char *cservername = canon_servername(servername);
5099
5100         r->version              = driver->version;
5101
5102         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5103         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5104         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5105         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5106
5107         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5108                                driver->architecture,
5109                                driver->version,
5110                                driver->driver_path,
5111                                r->driver_path);
5112
5113         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5114                                driver->architecture,
5115                                driver->version,
5116                                driver->data_file,
5117                                r->data_file);
5118
5119         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5120                                driver->architecture,
5121                                driver->version,
5122                                driver->config_file,
5123                                r->config_file);
5124
5125         r->driver_attributes    = 0;
5126         r->config_version       = 0;
5127         r->driver_version       = 0;
5128
5129         return WERR_OK;
5130 }
5131 /********************************************************************
5132  * fill a spoolss_DriverInfo6 struct
5133  ********************************************************************/
5134
5135 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5136                                         struct spoolss_DriverInfo6 *r,
5137                                         const struct spoolss_DriverInfo8 *driver,
5138                                         const char *servername)
5139 {
5140         const char *cservername = canon_servername(servername);
5141         WERROR result;
5142
5143         r->version              = driver->version;
5144
5145         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5146         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5147         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5148         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5149
5150         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5151                                driver->architecture,
5152                                driver->version,
5153                                driver->driver_path,
5154                                r->driver_path);
5155
5156         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5157                                driver->architecture,
5158                                driver->version,
5159                                driver->data_file,
5160                                r->data_file);
5161
5162         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5163                                driver->architecture,
5164                                driver->version,
5165                                driver->config_file,
5166                                r->config_file);
5167
5168         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5169                                driver->architecture,
5170                                driver->version,
5171                                driver->help_file,
5172                                r->help_file);
5173
5174         FILL_DRIVER_STRING(mem_ctx,
5175                            driver->monitor_name,
5176                            r->monitor_name);
5177
5178         FILL_DRIVER_STRING(mem_ctx,
5179                            driver->default_datatype,
5180                            r->default_datatype);
5181
5182         result = string_array_from_driver_info(mem_ctx,
5183                                                driver->dependent_files,
5184                                                &r->dependent_files,
5185                                                cservername,
5186                                                driver->architecture,
5187                                                driver->version);
5188         if (!W_ERROR_IS_OK(result)) {
5189                 return result;
5190         }
5191
5192         result = string_array_from_driver_info(mem_ctx,
5193                                                driver->previous_names,
5194                                                &r->previous_names,
5195                                                NULL, NULL, 0);
5196         if (!W_ERROR_IS_OK(result)) {
5197                 return result;
5198         }
5199
5200         r->driver_date          = driver->driver_date;
5201         r->driver_version       = driver->driver_version;
5202
5203         FILL_DRIVER_STRING(mem_ctx,
5204                            driver->manufacturer_name,
5205                            r->manufacturer_name);
5206         FILL_DRIVER_STRING(mem_ctx,
5207                            driver->manufacturer_url,
5208                            r->manufacturer_url);
5209         FILL_DRIVER_STRING(mem_ctx,
5210                            driver->hardware_id,
5211                            r->hardware_id);
5212         FILL_DRIVER_STRING(mem_ctx,
5213                            driver->provider,
5214                            r->provider);
5215
5216         return WERR_OK;
5217 }
5218
5219 /********************************************************************
5220  * fill a spoolss_DriverInfo8 struct
5221  ********************************************************************/
5222
5223 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5224                                         struct spoolss_DriverInfo8 *r,
5225                                         const struct spoolss_DriverInfo8 *driver,
5226                                         const char *servername)
5227 {
5228         const char *cservername = canon_servername(servername);
5229         WERROR result;
5230
5231         r->version              = driver->version;
5232
5233         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5234         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5235         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5236         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5237
5238         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5239                                driver->architecture,
5240                                driver->version,
5241                                driver->driver_path,
5242                                r->driver_path);
5243
5244         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5245                                driver->architecture,
5246                                driver->version,
5247                                driver->data_file,
5248                                r->data_file);
5249
5250         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5251                                driver->architecture,
5252                                driver->version,
5253                                driver->config_file,
5254                                r->config_file);
5255
5256         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5257                                driver->architecture,
5258                                driver->version,
5259                                driver->help_file,
5260                                r->help_file);
5261
5262         FILL_DRIVER_STRING(mem_ctx,
5263                            driver->monitor_name,
5264                            r->monitor_name);
5265
5266         FILL_DRIVER_STRING(mem_ctx,
5267                            driver->default_datatype,
5268                            r->default_datatype);
5269
5270         result = string_array_from_driver_info(mem_ctx,
5271                                                driver->dependent_files,
5272                                                &r->dependent_files,
5273                                                cservername,
5274                                                driver->architecture,
5275                                                driver->version);
5276         if (!W_ERROR_IS_OK(result)) {
5277                 return result;
5278         }
5279
5280         result = string_array_from_driver_info(mem_ctx,
5281                                                driver->previous_names,
5282                                                &r->previous_names,
5283                                                NULL, NULL, 0);
5284         if (!W_ERROR_IS_OK(result)) {
5285                 return result;
5286         }
5287
5288         r->driver_date          = driver->driver_date;
5289         r->driver_version       = driver->driver_version;
5290
5291         FILL_DRIVER_STRING(mem_ctx,
5292                            driver->manufacturer_name,
5293                            r->manufacturer_name);
5294         FILL_DRIVER_STRING(mem_ctx,
5295                            driver->manufacturer_url,
5296                            r->manufacturer_url);
5297         FILL_DRIVER_STRING(mem_ctx,
5298                            driver->hardware_id,
5299                            r->hardware_id);
5300         FILL_DRIVER_STRING(mem_ctx,
5301                            driver->provider,
5302                            r->provider);
5303
5304         FILL_DRIVER_STRING(mem_ctx,
5305                            driver->print_processor,
5306                            r->print_processor);
5307         FILL_DRIVER_STRING(mem_ctx,
5308                            driver->vendor_setup,
5309                            r->vendor_setup);
5310
5311         result = string_array_from_driver_info(mem_ctx,
5312                                                driver->color_profiles,
5313                                                &r->color_profiles,
5314                                                NULL, NULL, 0);
5315         if (!W_ERROR_IS_OK(result)) {
5316                 return result;
5317         }
5318
5319         FILL_DRIVER_STRING(mem_ctx,
5320                            driver->inf_path,
5321                            r->inf_path);
5322
5323         r->printer_driver_attributes    = driver->printer_driver_attributes;
5324
5325         result = string_array_from_driver_info(mem_ctx,
5326                                                driver->core_driver_dependencies,
5327                                                &r->core_driver_dependencies,
5328                                                NULL, NULL, 0);
5329         if (!W_ERROR_IS_OK(result)) {
5330                 return result;
5331         }
5332
5333         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5334         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5335
5336         return WERR_OK;
5337 }
5338
5339 #if 0 /* disabled until marshalling issues are resolved - gd */
5340 /********************************************************************
5341  ********************************************************************/
5342
5343 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5344                                           struct spoolss_DriverFileInfo *r,
5345                                           const char *cservername,
5346                                           const char *file_name,
5347                                           enum spoolss_DriverFileType file_type,
5348                                           uint32_t file_version)
5349 {
5350         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5351                                           cservername, file_name);
5352         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5353         r->file_type    = file_type;
5354         r->file_version = file_version;
5355
5356         return WERR_OK;
5357 }
5358
5359 /********************************************************************
5360  ********************************************************************/
5361
5362 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5363                                                  const struct spoolss_DriverInfo8 *driver,
5364                                                  const char *cservername,
5365                                                  struct spoolss_DriverFileInfo **info_p,
5366                                                  uint32_t *count_p)
5367 {
5368         struct spoolss_DriverFileInfo *info = NULL;
5369         uint32_t count = 0;
5370         WERROR result;
5371         uint32_t i;
5372
5373         *info_p = NULL;
5374         *count_p = 0;
5375
5376         if (strlen(driver->driver_path)) {
5377                 info = talloc_realloc(mem_ctx, info,
5378                                             struct spoolss_DriverFileInfo,
5379                                             count + 1);
5380                 W_ERROR_HAVE_NO_MEMORY(info);
5381                 result = fill_spoolss_DriverFileInfo(info,
5382                                                      &info[count],
5383                                                      cservername,
5384                                                      driver->driver_path,
5385                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5386                                                      0);
5387                 W_ERROR_NOT_OK_RETURN(result);
5388                 count++;
5389         }
5390
5391         if (strlen(driver->config_file)) {
5392                 info = talloc_realloc(mem_ctx, info,
5393                                             struct spoolss_DriverFileInfo,
5394                                             count + 1);
5395                 W_ERROR_HAVE_NO_MEMORY(info);
5396                 result = fill_spoolss_DriverFileInfo(info,
5397                                                      &info[count],
5398                                                      cservername,
5399                                                      driver->config_file,
5400                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5401                                                      0);
5402                 W_ERROR_NOT_OK_RETURN(result);
5403                 count++;
5404         }
5405
5406         if (strlen(driver->data_file)) {
5407                 info = talloc_realloc(mem_ctx, info,
5408                                             struct spoolss_DriverFileInfo,
5409                                             count + 1);
5410                 W_ERROR_HAVE_NO_MEMORY(info);
5411                 result = fill_spoolss_DriverFileInfo(info,
5412                                                      &info[count],
5413                                                      cservername,
5414                                                      driver->data_file,
5415                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5416                                                      0);
5417                 W_ERROR_NOT_OK_RETURN(result);
5418                 count++;
5419         }
5420
5421         if (strlen(driver->help_file)) {
5422                 info = talloc_realloc(mem_ctx, info,
5423                                             struct spoolss_DriverFileInfo,
5424                                             count + 1);
5425                 W_ERROR_HAVE_NO_MEMORY(info);
5426                 result = fill_spoolss_DriverFileInfo(info,
5427                                                      &info[count],
5428                                                      cservername,
5429                                                      driver->help_file,
5430                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5431                                                      0);
5432                 W_ERROR_NOT_OK_RETURN(result);
5433                 count++;
5434         }
5435
5436         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5437                 info = talloc_realloc(mem_ctx, info,
5438                                             struct spoolss_DriverFileInfo,
5439                                             count + 1);
5440                 W_ERROR_HAVE_NO_MEMORY(info);
5441                 result = fill_spoolss_DriverFileInfo(info,
5442                                                      &info[count],
5443                                                      cservername,
5444                                                      driver->dependent_files[i],
5445                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5446                                                      0);
5447                 W_ERROR_NOT_OK_RETURN(result);
5448                 count++;
5449         }
5450
5451         *info_p = info;
5452         *count_p = count;
5453
5454         return WERR_OK;
5455 }
5456
5457 /********************************************************************
5458  * fill a spoolss_DriverInfo101 struct
5459  ********************************************************************/
5460
5461 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5462                                           struct spoolss_DriverInfo101 *r,
5463                                           const struct spoolss_DriverInfo8 *driver,
5464                                           const char *servername)
5465 {
5466         const char *cservername = canon_servername(servername);
5467         WERROR result;
5468
5469         r->version              = driver->version;
5470
5471         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5472         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5473         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5474         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5475
5476         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5477                                                     cservername,
5478                                                     &r->file_info,
5479                                                     &r->file_count);
5480         if (!W_ERROR_IS_OK(result)) {
5481                 return result;
5482         }
5483
5484         FILL_DRIVER_STRING(mem_ctx,
5485                            driver->monitor_name,
5486                            r->monitor_name);
5487
5488         FILL_DRIVER_STRING(mem_ctx,
5489                            driver->default_datatype,
5490                            r->default_datatype);
5491
5492         result = string_array_from_driver_info(mem_ctx,
5493                                                driver->previous_names,
5494                                                &r->previous_names,
5495                                                NULL, NULL, 0);
5496         if (!W_ERROR_IS_OK(result)) {
5497                 return result;
5498         }
5499
5500         r->driver_date          = driver->driver_date;
5501         r->driver_version       = driver->driver_version;
5502
5503         FILL_DRIVER_STRING(mem_ctx,
5504                            driver->manufacturer_name,
5505                            r->manufacturer_name);
5506         FILL_DRIVER_STRING(mem_ctx,
5507                            driver->manufacturer_url,
5508                            r->manufacturer_url);
5509         FILL_DRIVER_STRING(mem_ctx,
5510                            driver->hardware_id,
5511                            r->hardware_id);
5512         FILL_DRIVER_STRING(mem_ctx,
5513                            driver->provider,
5514                            r->provider);
5515
5516         return WERR_OK;
5517 }
5518 #endif
5519 /********************************************************************
5520  ********************************************************************/
5521
5522 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5523                                                   const struct auth_session_info *session_info,
5524                                                   struct messaging_context *msg_ctx,
5525                                                   uint32_t level,
5526                                                   union spoolss_DriverInfo *r,
5527                                                   int snum,
5528                                                   const char *servername,
5529                                                   const char *architecture,
5530                                                   uint32_t version)
5531 {
5532         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5533         struct spoolss_DriverInfo8 *driver;
5534         WERROR result;
5535         struct dcerpc_binding_handle *b;
5536         TALLOC_CTX *tmp_ctx = NULL;
5537
5538         if (level == 101) {
5539                 return WERR_UNKNOWN_LEVEL;
5540         }
5541
5542         tmp_ctx = talloc_new(mem_ctx);
5543         if (!tmp_ctx) {
5544                 return WERR_NOMEM;
5545         }
5546
5547         result = winreg_printer_binding_handle(tmp_ctx,
5548                                                session_info,
5549                                                msg_ctx,
5550                                                &b);
5551         if (!W_ERROR_IS_OK(result)) {
5552                 goto done;
5553         }
5554
5555         result = winreg_get_printer(tmp_ctx, b,
5556                                     lp_const_servicename(snum),
5557                                     &pinfo2);
5558
5559         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5560                 win_errstr(result)));
5561
5562         if (!W_ERROR_IS_OK(result)) {
5563                 result = WERR_INVALID_PRINTER_NAME;
5564                 goto done;
5565         }
5566
5567         result = winreg_get_driver(tmp_ctx, b,
5568                                    architecture,
5569                                    pinfo2->drivername, version, &driver);
5570
5571         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5572                 win_errstr(result)));
5573
5574         if (!W_ERROR_IS_OK(result)) {
5575                 /*
5576                  * Is this a W2k client ?
5577                  */
5578
5579                 if (version < 3) {
5580                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5581                         goto done;
5582                 }
5583
5584                 /* Yes - try again with a WinNT driver. */
5585                 version = 2;
5586                 result = winreg_get_driver(tmp_ctx, b,
5587                                            architecture,
5588                                            pinfo2->drivername,
5589                                            version, &driver);
5590                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5591                         win_errstr(result)));
5592                 if (!W_ERROR_IS_OK(result)) {
5593                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5594                         goto done;
5595                 }
5596         }
5597
5598         /* these are allocated on mem_ctx and not tmp_ctx because they are
5599          * the 'return value' and need to utlive this call */
5600         switch (level) {
5601         case 1:
5602                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5603                 break;
5604         case 2:
5605                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5606                 break;
5607         case 3:
5608                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5609                 break;
5610         case 4:
5611                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5612                 break;
5613         case 5:
5614                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5615                 break;
5616         case 6:
5617                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5618                 break;
5619         case 8:
5620                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5621                 break;
5622 #if 0 /* disabled until marshalling issues are resolved - gd */
5623         case 101:
5624                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5625                 break;
5626 #endif
5627         default:
5628                 result = WERR_UNKNOWN_LEVEL;
5629                 break;
5630         }
5631
5632 done:
5633         talloc_free(tmp_ctx);
5634         return result;
5635 }
5636
5637 /****************************************************************
5638  _spoolss_GetPrinterDriver2
5639 ****************************************************************/
5640
5641 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5642                                   struct spoolss_GetPrinterDriver2 *r)
5643 {
5644         struct printer_handle *printer;
5645         WERROR result;
5646         uint32_t version = r->in.client_major_version;
5647
5648         int snum;
5649
5650         /* that's an [in out] buffer */
5651
5652         if (!r->in.buffer && (r->in.offered != 0)) {
5653                 return WERR_INVALID_PARAM;
5654         }
5655
5656         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5657
5658         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5659                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5660                 return WERR_INVALID_PRINTER_NAME;
5661         }
5662
5663         *r->out.needed = 0;
5664         *r->out.server_major_version = 0;
5665         *r->out.server_minor_version = 0;
5666
5667         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5668                 return WERR_BADFID;
5669         }
5670
5671         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5672                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5673                         "downgrading to v3\n"));
5674                 version = SPOOLSS_DRIVER_VERSION_200X;
5675         }
5676
5677         result = construct_printer_driver_info_level(p->mem_ctx,
5678                                                      get_session_info_system(),
5679                                                      p->msg_ctx,
5680                                                      r->in.level, r->out.info,
5681                                                      snum, printer->servername,
5682                                                      r->in.architecture,
5683                                                      version);
5684         if (!W_ERROR_IS_OK(result)) {
5685                 TALLOC_FREE(r->out.info);
5686                 return result;
5687         }
5688
5689         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5690                                                r->out.info, r->in.level);
5691         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5692
5693         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5694 }
5695
5696
5697 /****************************************************************
5698  _spoolss_StartPagePrinter
5699 ****************************************************************/
5700
5701 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5702                                  struct spoolss_StartPagePrinter *r)
5703 {
5704         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5705
5706         if (!Printer) {
5707                 DEBUG(3,("_spoolss_StartPagePrinter: "
5708                         "Error in startpageprinter printer handle\n"));
5709                 return WERR_BADFID;
5710         }
5711
5712         Printer->page_started = true;
5713         return WERR_OK;
5714 }
5715
5716 /****************************************************************
5717  _spoolss_EndPagePrinter
5718 ****************************************************************/
5719
5720 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5721                                struct spoolss_EndPagePrinter *r)
5722 {
5723         int snum;
5724
5725         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5726
5727         if (!Printer) {
5728                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5729                         OUR_HANDLE(r->in.handle)));
5730                 return WERR_BADFID;
5731         }
5732
5733         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5734                 return WERR_BADFID;
5735
5736         Printer->page_started = false;
5737         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5738
5739         return WERR_OK;
5740 }
5741
5742 /****************************************************************
5743  _spoolss_StartDocPrinter
5744 ****************************************************************/
5745
5746 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5747                                 struct spoolss_StartDocPrinter *r)
5748 {
5749         struct spoolss_DocumentInfo1 *info_1;
5750         int snum;
5751         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5752         WERROR werr;
5753         char *rhost;
5754         int rc;
5755
5756         if (!Printer) {
5757                 DEBUG(2,("_spoolss_StartDocPrinter: "
5758                         "Invalid handle (%s:%u:%u)\n",
5759                         OUR_HANDLE(r->in.handle)));
5760                 return WERR_BADFID;
5761         }
5762
5763         if (Printer->jobid) {
5764                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5765                           "StartDocPrinter called twice! "
5766                           "(existing jobid = %d)\n", Printer->jobid));
5767                 return WERR_INVALID_HANDLE;
5768         }
5769
5770         if (r->in.info_ctr->level != 1) {
5771                 return WERR_UNKNOWN_LEVEL;
5772         }
5773
5774         info_1 = r->in.info_ctr->info.info1;
5775
5776         /*
5777          * a nice thing with NT is it doesn't listen to what you tell it.
5778          * when asked to send _only_ RAW datas, it tries to send datas
5779          * in EMF format.
5780          *
5781          * So I add checks like in NT Server ...
5782          */
5783
5784         if (info_1->datatype) {
5785                 if (strcmp(info_1->datatype, "RAW") != 0) {
5786                         *r->out.job_id = 0;
5787                         return WERR_INVALID_DATATYPE;
5788                 }
5789         }
5790
5791         /* get the share number of the printer */
5792         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5793                 return WERR_BADFID;
5794         }
5795
5796         rc = get_remote_hostname(p->remote_address,
5797                                  &rhost,
5798                                  p->mem_ctx);
5799         if (rc < 0) {
5800                 return WERR_NOMEM;
5801         }
5802         if (strequal(rhost,"UNKNOWN")) {
5803                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5804                                                          p->mem_ctx);
5805                 if (rhost == NULL) {
5806                         return WERR_NOMEM;
5807                 }
5808         }
5809
5810         werr = print_job_start(p->session_info,
5811                                p->msg_ctx,
5812                                rhost,
5813                                snum,
5814                                info_1->document_name,
5815                                info_1->output_file,
5816                                Printer->devmode,
5817                                &Printer->jobid);
5818
5819         /* An error occured in print_job_start() so return an appropriate
5820            NT error code. */
5821
5822         if (!W_ERROR_IS_OK(werr)) {
5823                 return werr;
5824         }
5825
5826         Printer->document_started = true;
5827         *r->out.job_id = Printer->jobid;
5828
5829         return WERR_OK;
5830 }
5831
5832 /****************************************************************
5833  _spoolss_EndDocPrinter
5834 ****************************************************************/
5835
5836 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5837                               struct spoolss_EndDocPrinter *r)
5838 {
5839         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5840         NTSTATUS status;
5841         int snum;
5842
5843         if (!Printer) {
5844                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5845                         OUR_HANDLE(r->in.handle)));
5846                 return WERR_BADFID;
5847         }
5848
5849         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5850                 return WERR_BADFID;
5851         }
5852
5853         Printer->document_started = false;
5854         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5855         if (!NT_STATUS_IS_OK(status)) {
5856                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5857                           "print_job_end failed [%s]\n",
5858                           nt_errstr(status)));
5859         }
5860
5861         Printer->jobid = 0;
5862         return ntstatus_to_werror(status);
5863 }
5864
5865 /****************************************************************
5866  _spoolss_WritePrinter
5867 ****************************************************************/
5868
5869 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5870                              struct spoolss_WritePrinter *r)
5871 {
5872         ssize_t buffer_written;
5873         int snum;
5874         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5875
5876         if (!Printer) {
5877                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5878                         OUR_HANDLE(r->in.handle)));
5879                 *r->out.num_written = r->in._data_size;
5880                 return WERR_BADFID;
5881         }
5882
5883         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5884                 return WERR_BADFID;
5885
5886         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5887         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5888                                                    snum, Printer->jobid,
5889                                                    (const char *)r->in.data.data,
5890                                                    (size_t)r->in._data_size);
5891         if (buffer_written == (ssize_t)-1) {
5892                 *r->out.num_written = 0;
5893                 if (errno == ENOSPC)
5894                         return WERR_NO_SPOOL_SPACE;
5895                 else
5896                         return WERR_ACCESS_DENIED;
5897         }
5898
5899         *r->out.num_written = r->in._data_size;
5900
5901         return WERR_OK;
5902 }
5903
5904 /********************************************************************
5905  * api_spoolss_getprinter
5906  * called from the spoolss dispatcher
5907  *
5908  ********************************************************************/
5909
5910 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5911                               struct pipes_struct *p)
5912 {
5913         const struct auth_session_info *session_info = p->session_info;
5914         int snum;
5915         WERROR errcode = WERR_BADFUNC;
5916         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5917
5918         if (!Printer) {
5919                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5920                         OUR_HANDLE(handle)));
5921                 return WERR_BADFID;
5922         }
5923
5924         if (!get_printer_snum(p, handle, &snum, NULL))
5925                 return WERR_BADFID;
5926
5927         switch (command) {
5928         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5929                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5930                 break;
5931         case SPOOLSS_PRINTER_CONTROL_RESUME:
5932         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5933                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5934                 break;
5935         case SPOOLSS_PRINTER_CONTROL_PURGE:
5936                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5937                 break;
5938         default:
5939                 return WERR_UNKNOWN_LEVEL;
5940         }
5941
5942         return errcode;
5943 }
5944
5945
5946 /****************************************************************
5947  _spoolss_AbortPrinter
5948  * From MSDN: "Deletes printer's spool file if printer is configured
5949  * for spooling"
5950 ****************************************************************/
5951
5952 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5953                              struct spoolss_AbortPrinter *r)
5954 {
5955         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5956         int             snum;
5957         WERROR          errcode = WERR_OK;
5958
5959         if (!Printer) {
5960                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5961                         OUR_HANDLE(r->in.handle)));
5962                 return WERR_BADFID;
5963         }
5964
5965         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5966                 return WERR_BADFID;
5967
5968         if (!Printer->document_started) {
5969                 return WERR_SPL_NO_STARTDOC;
5970         }
5971
5972         errcode = print_job_delete(p->session_info,
5973                                    p->msg_ctx,
5974                                    snum,
5975                                    Printer->jobid);
5976
5977         return errcode;
5978 }
5979
5980 /********************************************************************
5981  * called by spoolss_api_setprinter
5982  * when updating a printer description
5983  ********************************************************************/
5984
5985 static WERROR update_printer_sec(struct policy_handle *handle,
5986                                  struct pipes_struct *p,
5987                                  struct sec_desc_buf *secdesc_ctr)
5988 {
5989         struct spoolss_security_descriptor *new_secdesc = NULL;
5990         struct spoolss_security_descriptor *old_secdesc = NULL;
5991         const char *printer;
5992         WERROR result;
5993         int snum;
5994         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5995         struct dcerpc_binding_handle *b;
5996         TALLOC_CTX *tmp_ctx = NULL;
5997
5998         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5999                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6000                          OUR_HANDLE(handle)));
6001
6002                 result = WERR_BADFID;
6003                 goto done;
6004         }
6005
6006         if (secdesc_ctr == NULL) {
6007                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6008                 result = WERR_INVALID_PARAM;
6009                 goto done;
6010         }
6011         printer = lp_const_servicename(snum);
6012
6013         /* Check the user has permissions to change the security
6014            descriptor.  By experimentation with two NT machines, the user
6015            requires Full Access to the printer to change security
6016            information. */
6017
6018         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6019                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6020                 result = WERR_ACCESS_DENIED;
6021                 goto done;
6022         }
6023
6024         tmp_ctx = talloc_new(p->mem_ctx);
6025         if (!tmp_ctx) {
6026                 return WERR_NOMEM;
6027         }
6028
6029         result = winreg_printer_binding_handle(tmp_ctx,
6030                                                get_session_info_system(),
6031                                                p->msg_ctx,
6032                                                &b);
6033         if (!W_ERROR_IS_OK(result)) {
6034                 goto done;
6035         }
6036
6037         /* NT seems to like setting the security descriptor even though
6038            nothing may have actually changed. */
6039         result = winreg_get_printer_secdesc(tmp_ctx, b,
6040                                             printer,
6041                                             &old_secdesc);
6042         if (!W_ERROR_IS_OK(result)) {
6043                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6044                 result = WERR_BADFID;
6045                 goto done;
6046         }
6047
6048         if (DEBUGLEVEL >= 10) {
6049                 struct security_acl *the_acl;
6050                 int i;
6051
6052                 the_acl = old_secdesc->dacl;
6053                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6054                            printer, the_acl->num_aces));
6055
6056                 for (i = 0; i < the_acl->num_aces; i++) {
6057                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6058                                            &the_acl->aces[i].trustee),
6059                                   the_acl->aces[i].access_mask));
6060                 }
6061
6062                 the_acl = secdesc_ctr->sd->dacl;
6063
6064                 if (the_acl) {
6065                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6066                                    printer, the_acl->num_aces));
6067
6068                         for (i = 0; i < the_acl->num_aces; i++) {
6069                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6070                                                    &the_acl->aces[i].trustee),
6071                                            the_acl->aces[i].access_mask));
6072                         }
6073                 } else {
6074                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6075                 }
6076         }
6077
6078         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6079         if (new_secdesc == NULL) {
6080                 result = WERR_NOMEM;
6081                 goto done;
6082         }
6083
6084         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6085                 result = WERR_OK;
6086                 goto done;
6087         }
6088
6089         result = winreg_set_printer_secdesc(tmp_ctx, b,
6090                                             printer,
6091                                             new_secdesc);
6092
6093 done:
6094         talloc_free(tmp_ctx);
6095         return result;
6096 }
6097
6098 /********************************************************************
6099  Canonicalize printer info from a client
6100  ********************************************************************/
6101
6102 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6103                              struct spoolss_SetPrinterInfo2 *info2,
6104                              int snum)
6105 {
6106         fstring printername;
6107         const char *p;
6108
6109         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6110                 "portname=%s drivername=%s comment=%s location=%s\n",
6111                 info2->servername, info2->printername, info2->sharename,
6112                 info2->portname, info2->drivername, info2->comment,
6113                 info2->location));
6114
6115         /* we force some elements to "correct" values */
6116         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6117         if (info2->servername == NULL) {
6118                 return false;
6119         }
6120         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6121         if (info2->sharename == NULL) {
6122                 return false;
6123         }
6124
6125         /* check to see if we allow printername != sharename */
6126         if (lp_force_printername(snum)) {
6127                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6128                                         lp_netbios_name(), info2->sharename);
6129         } else {
6130                 /* make sure printername is in \\server\printername format */
6131                 fstrcpy(printername, info2->printername);
6132                 p = printername;
6133                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6134                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6135                                 p++;
6136                 }
6137
6138                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6139                                         lp_netbios_name(), p);
6140         }
6141         if (info2->printername == NULL) {
6142                 return false;
6143         }
6144
6145         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6146         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6147
6148         return true;
6149 }
6150
6151 /****************************************************************************
6152 ****************************************************************************/
6153
6154 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6155 {
6156         char *cmd = lp_addport_cmd(talloc_tos());
6157         char *command = NULL;
6158         int ret;
6159         bool is_print_op = false;
6160
6161         if ( !*cmd ) {
6162                 return WERR_ACCESS_DENIED;
6163         }
6164
6165         command = talloc_asprintf(ctx,
6166                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6167         if (!command) {
6168                 return WERR_NOMEM;
6169         }
6170
6171         if ( token )
6172                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6173
6174         DEBUG(10,("Running [%s]\n", command));
6175
6176         /********* BEGIN SePrintOperatorPrivilege **********/
6177
6178         if ( is_print_op )
6179                 become_root();
6180
6181         ret = smbrun(command, NULL);
6182
6183         if ( is_print_op )
6184                 unbecome_root();
6185
6186         /********* END SePrintOperatorPrivilege **********/
6187
6188         DEBUGADD(10,("returned [%d]\n", ret));
6189
6190         TALLOC_FREE(command);
6191
6192         if ( ret != 0 ) {
6193                 return WERR_ACCESS_DENIED;
6194         }
6195
6196         return WERR_OK;
6197 }
6198
6199 /****************************************************************************
6200 ****************************************************************************/
6201
6202 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6203                                    int snum)
6204 {
6205         /*
6206          * As we do not know if we are embedded in the file server process
6207          * or not, we have to pretend that all shares are in use.
6208          */
6209         return true;
6210 }
6211
6212 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6213                              struct spoolss_SetPrinterInfo2 *info2,
6214                              const char *remote_machine,
6215                              struct messaging_context *msg_ctx)
6216 {
6217         char *cmd = lp_addprinter_cmd(talloc_tos());
6218         char **qlines;
6219         char *command = NULL;
6220         int numlines;
6221         int ret;
6222         int fd;
6223         bool is_print_op = false;
6224
6225         if (!remote_machine) {
6226                 return false;
6227         }
6228
6229         command = talloc_asprintf(ctx,
6230                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6231                         cmd, info2->printername, info2->sharename,
6232                         info2->portname, info2->drivername,
6233                         info2->location, info2->comment, remote_machine);
6234         if (!command) {
6235                 return false;
6236         }
6237
6238         if ( token )
6239                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6240
6241         DEBUG(10,("Running [%s]\n", command));
6242
6243         /********* BEGIN SePrintOperatorPrivilege **********/
6244
6245         if ( is_print_op )
6246                 become_root();
6247
6248         if ( (ret = smbrun(command, &fd)) == 0 ) {
6249                 /* Tell everyone we updated smb.conf. */
6250                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6251         }
6252
6253         if ( is_print_op )
6254                 unbecome_root();
6255
6256         /********* END SePrintOperatorPrivilege **********/
6257
6258         DEBUGADD(10,("returned [%d]\n", ret));
6259
6260         TALLOC_FREE(command);
6261
6262         if ( ret != 0 ) {
6263                 if (fd != -1)
6264                         close(fd);
6265                 return false;
6266         }
6267
6268         /* reload our services immediately */
6269         become_root();
6270         reload_services(NULL, spoolss_conn_snum_used, false);
6271         unbecome_root();
6272
6273         numlines = 0;
6274         /* Get lines and convert them back to dos-codepage */
6275         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6276         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6277         close(fd);
6278
6279         /* Set the portname to what the script says the portname should be. */
6280         /* but don't require anything to be return from the script exit a good error code */
6281
6282         if (numlines) {
6283                 /* Set the portname to what the script says the portname should be. */
6284                 info2->portname = talloc_strdup(ctx, qlines[0]);
6285                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6286         }
6287
6288         TALLOC_FREE(qlines);
6289         return true;
6290 }
6291
6292 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6293                                const struct auth_session_info *session_info,
6294                                struct messaging_context *msg_ctx,
6295                                int snum,
6296                                struct spoolss_SetPrinterInfo2 *printer,
6297                                struct spoolss_PrinterInfo2 *old_printer)
6298 {
6299         bool force_update = (old_printer == NULL);
6300         const char *dnsdomname;
6301         const char *longname;
6302         const char *uncname;
6303         const char *spooling;
6304         DATA_BLOB buffer;
6305         WERROR result = WERR_OK;
6306         struct dcerpc_binding_handle *b;
6307         TALLOC_CTX *tmp_ctx;
6308         bool ok;
6309
6310         tmp_ctx = talloc_new(mem_ctx);
6311         if (!tmp_ctx) {
6312                 return WERR_NOMEM;
6313         }
6314
6315         result = winreg_printer_binding_handle(tmp_ctx,
6316                                                session_info,
6317                                                msg_ctx,
6318                                                &b);
6319         if (!W_ERROR_IS_OK(result)) {
6320                 goto done;
6321         }
6322
6323         if (printer->drivername != NULL &&
6324             (force_update ||
6325              !strequal(printer->drivername, old_printer->drivername))) {
6326                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6327                 if (!ok) {
6328                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6329                         result = WERR_INVALID_DATA;
6330                         goto done;
6331                 }
6332                 result = winreg_set_printer_dataex(tmp_ctx, b,
6333                                           printer->sharename,
6334                                           SPOOL_DSSPOOLER_KEY,
6335                                           SPOOL_REG_DRIVERNAME,
6336                                           REG_SZ,
6337                                           buffer.data,
6338                                           buffer.length);
6339                 if (!W_ERROR_IS_OK(result)) {
6340                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6341                         goto done;
6342                 }
6343
6344                 if (!force_update) {
6345                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6346                                 printer->drivername));
6347
6348                         notify_printer_driver(server_event_context(), msg_ctx,
6349                                               snum, printer->drivername ?
6350                                               printer->drivername : "");
6351                 }
6352         }
6353
6354         if (printer->comment != NULL &&
6355             (force_update ||
6356              !strequal(printer->comment, old_printer->comment))) {
6357                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6358                 if (!ok) {
6359                         DEBUG(0, ("comment data corrupted\n"));
6360                         result = WERR_INVALID_DATA;
6361                         goto done;
6362                 }
6363                 result = winreg_set_printer_dataex(tmp_ctx, b,
6364                                           printer->sharename,
6365                                           SPOOL_DSSPOOLER_KEY,
6366                                           SPOOL_REG_DESCRIPTION,
6367                                           REG_SZ,
6368                                           buffer.data,
6369                                           buffer.length);
6370                 if (!W_ERROR_IS_OK(result)) {
6371                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6372                         goto done;
6373                 }
6374
6375                 if (!force_update) {
6376                         notify_printer_comment(server_event_context(), msg_ctx,
6377                                                snum, printer->comment ?
6378                                                printer->comment : "");
6379                 }
6380         }
6381
6382         if (printer->sharename != NULL &&
6383             (force_update ||
6384              !strequal(printer->sharename, old_printer->sharename))) {
6385                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6386                 if (!ok) {
6387                         DEBUG(0, ("sharename data corrupted\n"));
6388                         result = WERR_INVALID_DATA;
6389                         goto done;
6390                 }
6391                 result = winreg_set_printer_dataex(tmp_ctx, b,
6392                                           printer->sharename,
6393                                           SPOOL_DSSPOOLER_KEY,
6394                                           SPOOL_REG_PRINTSHARENAME,
6395                                           REG_SZ,
6396                                           buffer.data,
6397                                           buffer.length);
6398                 if (!W_ERROR_IS_OK(result)) {
6399                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6400                         goto done;
6401                 }
6402
6403                 if (!force_update) {
6404                         notify_printer_sharename(server_event_context(),
6405                                                  msg_ctx,
6406                                                  snum, printer->sharename ?
6407                                                  printer->sharename : "");
6408                 }
6409         }
6410
6411         if (printer->printername != NULL &&
6412             (force_update ||
6413              !strequal(printer->printername, old_printer->printername))) {
6414                 const char *p;
6415
6416                 p = strrchr(printer->printername, '\\' );
6417                 if (p != NULL) {
6418                         p++;
6419                 } else {
6420                         p = printer->printername;
6421                 }
6422
6423                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6424                 if (!ok) {
6425                         DEBUG(0, ("printername data corrupted\n"));
6426                         result = WERR_INVALID_DATA;
6427                         goto done;
6428                 }
6429                 result = winreg_set_printer_dataex(tmp_ctx, b,
6430                                           printer->sharename,
6431                                           SPOOL_DSSPOOLER_KEY,
6432                                           SPOOL_REG_PRINTERNAME,
6433                                           REG_SZ,
6434                                           buffer.data,
6435                                           buffer.length);
6436                 if (!W_ERROR_IS_OK(result)) {
6437                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6438                         goto done;
6439                 }
6440
6441                 if (!force_update) {
6442                         notify_printer_printername(server_event_context(),
6443                                                    msg_ctx, snum, p ? p : "");
6444                 }
6445         }
6446
6447         if (printer->portname != NULL &&
6448             (force_update ||
6449              !strequal(printer->portname, old_printer->portname))) {
6450                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6451                 if (!ok) {
6452                         DEBUG(0, ("portname data corrupted\n"));
6453                         result = WERR_INVALID_DATA;
6454                         goto done;
6455                 }
6456                 result = winreg_set_printer_dataex(tmp_ctx, b,
6457                                           printer->sharename,
6458                                           SPOOL_DSSPOOLER_KEY,
6459                                           SPOOL_REG_PORTNAME,
6460                                           REG_SZ,
6461                                           buffer.data,
6462                                           buffer.length);
6463                 if (!W_ERROR_IS_OK(result)) {
6464                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6465                         goto done;
6466                 }
6467
6468                 if (!force_update) {
6469                         notify_printer_port(server_event_context(),
6470                                             msg_ctx, snum, printer->portname ?
6471                                             printer->portname : "");
6472                 }
6473         }
6474
6475         if (printer->location != NULL &&
6476             (force_update ||
6477              !strequal(printer->location, old_printer->location))) {
6478                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6479                 if (!ok) {
6480                         DEBUG(0, ("location data corrupted\n"));
6481                         result = WERR_INVALID_DATA;
6482                         goto done;
6483                 }
6484                 result = winreg_set_printer_dataex(tmp_ctx, b,
6485                                           printer->sharename,
6486                                           SPOOL_DSSPOOLER_KEY,
6487                                           SPOOL_REG_LOCATION,
6488                                           REG_SZ,
6489                                           buffer.data,
6490                                           buffer.length);
6491                 if (!W_ERROR_IS_OK(result)) {
6492                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6493                         goto done;
6494                 }
6495
6496                 if (!force_update) {
6497                         notify_printer_location(server_event_context(),
6498                                                 msg_ctx, snum,
6499                                                 printer->location ?
6500                                                 printer->location : "");
6501                 }
6502         }
6503
6504         if (printer->sepfile != NULL &&
6505             (force_update ||
6506              !strequal(printer->sepfile, old_printer->sepfile))) {
6507                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6508                 if (!ok) {
6509                         DEBUG(0, ("sepfile data corrupted\n"));
6510                         result = WERR_INVALID_DATA;
6511                         goto done;
6512                 }
6513                 result = winreg_set_printer_dataex(tmp_ctx, b,
6514                                           printer->sharename,
6515                                           SPOOL_DSSPOOLER_KEY,
6516                                           SPOOL_REG_PRINTSEPARATORFILE,
6517                                           REG_SZ,
6518                                           buffer.data,
6519                                           buffer.length);
6520                 if (!W_ERROR_IS_OK(result)) {
6521                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6522                         goto done;
6523                 }
6524
6525                 if (!force_update) {
6526                         notify_printer_sepfile(server_event_context(),
6527                                                msg_ctx, snum,
6528                                                printer->sepfile ?
6529                                                printer->sepfile : "");
6530                 }
6531         }
6532
6533         if (printer->starttime != 0 &&
6534             (force_update ||
6535              printer->starttime != old_printer->starttime)) {
6536                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6537                 SIVAL(buffer.data, 0, printer->starttime);
6538                 result = winreg_set_printer_dataex(tmp_ctx, b,
6539                                           printer->sharename,
6540                                           SPOOL_DSSPOOLER_KEY,
6541                                           SPOOL_REG_PRINTSTARTTIME,
6542                                           REG_DWORD,
6543                                           buffer.data,
6544                                           buffer.length);
6545                 if (!W_ERROR_IS_OK(result)) {
6546                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6547                         goto done;
6548                 }
6549         }
6550
6551         if (printer->untiltime != 0 &&
6552             (force_update ||
6553              printer->untiltime != old_printer->untiltime)) {
6554                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6555                 SIVAL(buffer.data, 0, printer->untiltime);
6556                 result = winreg_set_printer_dataex(tmp_ctx, b,
6557                                           printer->sharename,
6558                                           SPOOL_DSSPOOLER_KEY,
6559                                           SPOOL_REG_PRINTENDTIME,
6560                                           REG_DWORD,
6561                                           buffer.data,
6562                                           buffer.length);
6563                 if (!W_ERROR_IS_OK(result)) {
6564                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6565                         goto done;
6566                 }
6567         }
6568
6569         if (force_update || printer->priority != old_printer->priority) {
6570                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6571                 SIVAL(buffer.data, 0, printer->priority);
6572                 result = winreg_set_printer_dataex(tmp_ctx, b,
6573                                           printer->sharename,
6574                                           SPOOL_DSSPOOLER_KEY,
6575                                           SPOOL_REG_PRIORITY,
6576                                           REG_DWORD,
6577                                           buffer.data,
6578                                           buffer.length);
6579                 if (!W_ERROR_IS_OK(result)) {
6580                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6581                         goto done;
6582                 }
6583         }
6584
6585         if (force_update || printer->attributes != old_printer->attributes) {
6586                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6587                 SIVAL(buffer.data, 0, (printer->attributes &
6588                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6589                 result = winreg_set_printer_dataex(tmp_ctx, b,
6590                                           printer->sharename,
6591                                           SPOOL_DSSPOOLER_KEY,
6592                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6593                                           REG_DWORD,
6594                                           buffer.data,
6595                                           buffer.length);
6596                 if (!W_ERROR_IS_OK(result)) {
6597                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6598                         goto done;
6599                 }
6600
6601                 switch (printer->attributes & 0x3) {
6602                         case 0:
6603                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6604                                 break;
6605                         case 1:
6606                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6607                                 break;
6608                         case 2:
6609                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6610                                 break;
6611                         default:
6612                                 spooling = "unknown";
6613                 }
6614                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6615                 if (!ok) {
6616                         DEBUG(0, ("printSpooling data corrupted\n"));
6617                         result = WERR_INVALID_DATA;
6618                         goto done;
6619                 }
6620                 winreg_set_printer_dataex(tmp_ctx, b,
6621                                           printer->sharename,
6622                                           SPOOL_DSSPOOLER_KEY,
6623                                           SPOOL_REG_PRINTSPOOLING,
6624                                           REG_SZ,
6625                                           buffer.data,
6626                                           buffer.length);
6627         }
6628
6629         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6630         if (!ok) {
6631                 DEBUG(0, ("shortServerName data corrupted\n"));
6632                 result = WERR_INVALID_DATA;
6633                 goto done;
6634         }
6635         result = winreg_set_printer_dataex(tmp_ctx, b,
6636                                   printer->sharename,
6637                                   SPOOL_DSSPOOLER_KEY,
6638                                   SPOOL_REG_SHORTSERVERNAME,
6639                                   REG_SZ,
6640                                   buffer.data,
6641                                   buffer.length);
6642         if (!W_ERROR_IS_OK(result)) {
6643                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6644                 goto done;
6645         }
6646
6647         dnsdomname = get_mydnsfullname();
6648         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6649                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6650         } else {
6651                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6652         }
6653         if (longname == NULL) {
6654                 result = WERR_NOMEM;
6655                 goto done;
6656         }
6657
6658         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6659         if (!ok) {
6660                 DEBUG(0, ("longname data corrupted\n"));
6661                 result = WERR_INVALID_DATA;
6662                 goto done;
6663         }
6664         result = winreg_set_printer_dataex(tmp_ctx, b,
6665                                            printer->sharename,
6666                                            SPOOL_DSSPOOLER_KEY,
6667                                            SPOOL_REG_SERVERNAME,
6668                                            REG_SZ,
6669                                            buffer.data,
6670                                            buffer.length);
6671         if (!W_ERROR_IS_OK(result)) {
6672                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6673                 goto done;
6674         }
6675
6676         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6677                                   lp_netbios_name(), printer->sharename);
6678         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6679         if (!ok) {
6680                 DEBUG(0, ("uncName data corrupted\n"));
6681                 result = WERR_INVALID_DATA;
6682                 goto done;
6683         }
6684         result = winreg_set_printer_dataex(tmp_ctx, b,
6685                                   printer->sharename,
6686                                   SPOOL_DSSPOOLER_KEY,
6687                                   SPOOL_REG_UNCNAME,
6688                                   REG_SZ,
6689                                   buffer.data,
6690                                   buffer.length);
6691         if (!W_ERROR_IS_OK(result)) {
6692                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6693                 goto done;
6694         }
6695
6696 done:
6697         talloc_free(tmp_ctx);
6698         return result;
6699 }
6700
6701 /********************************************************************
6702  * Called by spoolss_api_setprinter
6703  * when updating a printer description.
6704  ********************************************************************/
6705
6706 static WERROR update_printer(struct pipes_struct *p,
6707                              struct policy_handle *handle,
6708                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6709                              struct spoolss_DeviceMode *devmode)
6710 {
6711         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6712         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6713         struct spoolss_PrinterInfo2 *old_printer;
6714         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6715         int snum;
6716         WERROR result = WERR_OK;
6717         TALLOC_CTX *tmp_ctx;
6718         struct dcerpc_binding_handle *b;
6719
6720         DEBUG(8,("update_printer\n"));
6721
6722         tmp_ctx = talloc_new(p->mem_ctx);
6723         if (tmp_ctx == NULL) {
6724                 return WERR_NOMEM;
6725         }
6726
6727         if (!Printer) {
6728                 result = WERR_BADFID;
6729                 goto done;
6730         }
6731
6732         if (!get_printer_snum(p, handle, &snum, NULL)) {
6733                 result = WERR_BADFID;
6734                 goto done;
6735         }
6736
6737         result = winreg_printer_binding_handle(tmp_ctx,
6738                                                get_session_info_system(),
6739                                                p->msg_ctx,
6740                                                &b);
6741         if (!W_ERROR_IS_OK(result)) {
6742                 goto done;
6743         }
6744
6745         result = winreg_get_printer(tmp_ctx, b,
6746                                     lp_const_servicename(snum),
6747                                     &old_printer);
6748         if (!W_ERROR_IS_OK(result)) {
6749                 result = WERR_BADFID;
6750                 goto done;
6751         }
6752
6753         /* Do sanity check on the requested changes for Samba */
6754         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6755                 result = WERR_INVALID_PARAM;
6756                 goto done;
6757         }
6758
6759         /* FIXME!!! If the driver has changed we really should verify that
6760            it is installed before doing much else   --jerry */
6761
6762         /* Check calling user has permission to update printer description */
6763         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6764                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6765                 result = WERR_ACCESS_DENIED;
6766                 goto done;
6767         }
6768
6769         /* Call addprinter hook */
6770         /* Check changes to see if this is really needed */
6771
6772         if (*lp_addprinter_cmd(talloc_tos()) &&
6773                         (!strequal(printer->drivername, old_printer->drivername) ||
6774                          !strequal(printer->comment, old_printer->comment) ||
6775                          !strequal(printer->portname, old_printer->portname) ||
6776                          !strequal(printer->location, old_printer->location)) )
6777         {
6778                 char *raddr;
6779
6780                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6781                                                          p->mem_ctx);
6782                 if (raddr == NULL) {
6783                         return WERR_NOMEM;
6784                 }
6785
6786                 /* add_printer_hook() will call reload_services() */
6787                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6788                                       printer, raddr,
6789                                       p->msg_ctx)) {
6790                         result = WERR_ACCESS_DENIED;
6791                         goto done;
6792                 }
6793         }
6794
6795         result = update_dsspooler(tmp_ctx,
6796                                   get_session_info_system(),
6797                                   p->msg_ctx,
6798                                   snum,
6799                                   printer,
6800                                   old_printer);
6801         if (!W_ERROR_IS_OK(result)) {
6802                 goto done;
6803         }
6804
6805         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6806
6807         if (devmode == NULL) {
6808                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6809         }
6810         result = winreg_update_printer(tmp_ctx, b,
6811                                        printer->sharename,
6812                                        printer_mask,
6813                                        printer,
6814                                        devmode,
6815                                        NULL);
6816
6817 done:
6818         talloc_free(tmp_ctx);
6819
6820         return result;
6821 }
6822
6823 /****************************************************************************
6824 ****************************************************************************/
6825 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6826                                            struct policy_handle *handle,
6827                                            struct spoolss_SetPrinterInfo7 *info7)
6828 {
6829 #ifdef HAVE_ADS
6830         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6831         WERROR result;
6832         int snum;
6833         struct printer_handle *Printer;
6834
6835         if ( lp_security() != SEC_ADS ) {
6836                 return WERR_UNKNOWN_LEVEL;
6837         }
6838
6839         Printer = find_printer_index_by_hnd(p, handle);
6840
6841         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6842
6843         if (!Printer)
6844                 return WERR_BADFID;
6845
6846         if (!get_printer_snum(p, handle, &snum, NULL))
6847                 return WERR_BADFID;
6848
6849         result = winreg_get_printer_internal(p->mem_ctx,
6850                                     get_session_info_system(),
6851                                     p->msg_ctx,
6852                                     lp_servicename(talloc_tos(), snum),
6853                                     &pinfo2);
6854         if (!W_ERROR_IS_OK(result)) {
6855                 return WERR_BADFID;
6856         }
6857
6858         nt_printer_publish(pinfo2,
6859                            get_session_info_system(),
6860                            p->msg_ctx,
6861                            pinfo2,
6862                            info7->action);
6863
6864         TALLOC_FREE(pinfo2);
6865         return WERR_OK;
6866 #else
6867         return WERR_UNKNOWN_LEVEL;
6868 #endif
6869 }
6870
6871 /********************************************************************
6872  ********************************************************************/
6873
6874 static WERROR update_printer_devmode(struct pipes_struct *p,
6875                                      struct policy_handle *handle,
6876                                      struct spoolss_DeviceMode *devmode)
6877 {
6878         int snum;
6879         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6880         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6881
6882         DEBUG(8,("update_printer_devmode\n"));
6883
6884         if (!Printer) {
6885                 return WERR_BADFID;
6886         }
6887
6888         if (!get_printer_snum(p, handle, &snum, NULL)) {
6889                 return WERR_BADFID;
6890         }
6891
6892         /* Check calling user has permission to update printer description */
6893         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6894                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6895                 return WERR_ACCESS_DENIED;
6896         }
6897
6898         return winreg_update_printer_internal(p->mem_ctx,
6899                                      get_session_info_system(),
6900                                      p->msg_ctx,
6901                                      lp_const_servicename(snum),
6902                                      info2_mask,
6903                                      NULL,
6904                                      devmode,
6905                                      NULL);
6906 }
6907
6908
6909 /****************************************************************
6910  _spoolss_SetPrinter
6911 ****************************************************************/
6912
6913 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6914                            struct spoolss_SetPrinter *r)
6915 {
6916         WERROR result;
6917
6918         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6919
6920         if (!Printer) {
6921                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6922                         OUR_HANDLE(r->in.handle)));
6923                 return WERR_BADFID;
6924         }
6925
6926         /* check the level */
6927         switch (r->in.info_ctr->level) {
6928                 case 0:
6929                         return control_printer(r->in.handle, r->in.command, p);
6930                 case 2:
6931                         result = update_printer(p, r->in.handle,
6932                                                 r->in.info_ctr,
6933                                                 r->in.devmode_ctr->devmode);
6934                         if (!W_ERROR_IS_OK(result))
6935                                 return result;
6936                         if (r->in.secdesc_ctr->sd)
6937                                 result = update_printer_sec(r->in.handle, p,
6938                                                             r->in.secdesc_ctr);
6939                         return result;
6940                 case 3:
6941                         return update_printer_sec(r->in.handle, p,
6942                                                   r->in.secdesc_ctr);
6943                 case 7:
6944                         return publish_or_unpublish_printer(p, r->in.handle,
6945                                                             r->in.info_ctr->info.info7);
6946                 case 8:
6947                         return update_printer_devmode(p, r->in.handle,
6948                                                       r->in.devmode_ctr->devmode);
6949                 default:
6950                         return WERR_UNKNOWN_LEVEL;
6951         }
6952 }
6953
6954 /****************************************************************
6955  _spoolss_FindClosePrinterNotify
6956 ****************************************************************/
6957
6958 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6959                                        struct spoolss_FindClosePrinterNotify *r)
6960 {
6961         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6962
6963         if (!Printer) {
6964                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6965                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6966                 return WERR_BADFID;
6967         }
6968
6969         if (Printer->notify.cli_chan != NULL &&
6970             Printer->notify.cli_chan->active_connections > 0) {
6971                 int snum = -1;
6972
6973                 if (Printer->printer_type == SPLHND_PRINTER) {
6974                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6975                                 return WERR_BADFID;
6976                         }
6977                 }
6978
6979                 srv_spoolss_replycloseprinter(snum, Printer);
6980         }
6981
6982         Printer->notify.flags=0;
6983         Printer->notify.options=0;
6984         Printer->notify.localmachine[0]='\0';
6985         Printer->notify.printerlocal=0;
6986         TALLOC_FREE(Printer->notify.option);
6987
6988         return WERR_OK;
6989 }
6990
6991 /****************************************************************
6992  _spoolss_AddJob
6993 ****************************************************************/
6994
6995 WERROR _spoolss_AddJob(struct pipes_struct *p,
6996                        struct spoolss_AddJob *r)
6997 {
6998         if (!r->in.buffer && (r->in.offered != 0)) {
6999                 return WERR_INVALID_PARAM;
7000         }
7001
7002         /* this is what a NT server returns for AddJob. AddJob must fail on
7003          * non-local printers */
7004
7005         if (r->in.level != 1) {
7006                 return WERR_UNKNOWN_LEVEL;
7007         }
7008
7009         return WERR_INVALID_PARAM;
7010 }
7011
7012 /****************************************************************************
7013 fill_job_info1
7014 ****************************************************************************/
7015
7016 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7017                              struct spoolss_JobInfo1 *r,
7018                              const print_queue_struct *queue,
7019                              int position, int snum,
7020                              struct spoolss_PrinterInfo2 *pinfo2)
7021 {
7022         struct tm *t;
7023
7024         t = gmtime(&queue->time);
7025
7026         r->job_id               = queue->sysjob;
7027
7028         r->printer_name         = lp_servicename(mem_ctx, snum);
7029         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7030         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7031         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7032         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7033         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7034         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7035         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7036         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7037         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7038         r->text_status          = talloc_strdup(mem_ctx, "");
7039         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7040
7041         r->status               = nt_printj_status(queue->status);
7042         r->priority             = queue->priority;
7043         r->position             = position;
7044         r->total_pages          = queue->page_count;
7045         r->pages_printed        = 0; /* ??? */
7046
7047         init_systemtime(&r->submitted, t);
7048
7049         return WERR_OK;
7050 }
7051
7052 /****************************************************************************
7053 fill_job_info2
7054 ****************************************************************************/
7055
7056 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7057                              struct spoolss_JobInfo2 *r,
7058                              const print_queue_struct *queue,
7059                              int position, int snum,
7060                              struct spoolss_PrinterInfo2 *pinfo2,
7061                              struct spoolss_DeviceMode *devmode)
7062 {
7063         struct tm *t;
7064
7065         t = gmtime(&queue->time);
7066
7067         r->job_id               = queue->sysjob;
7068
7069         r->printer_name         = lp_servicename(mem_ctx, snum);
7070         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7071         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7072         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7073         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7074         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7075         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7076         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7077         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7078         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7079         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7080         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7081         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7082         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7083         r->parameters           = talloc_strdup(mem_ctx, "");
7084         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7085         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7086         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7087
7088         r->devmode              = devmode;
7089
7090         r->text_status          = talloc_strdup(mem_ctx, "");
7091         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7092
7093         r->secdesc              = NULL;
7094
7095         r->status               = nt_printj_status(queue->status);
7096         r->priority             = queue->priority;
7097         r->position             = position;
7098         r->start_time           = 0;
7099         r->until_time           = 0;
7100         r->total_pages          = queue->page_count;
7101         r->size                 = queue->size;
7102         init_systemtime(&r->submitted, t);
7103         r->time                 = 0;
7104         r->pages_printed        = 0; /* ??? */
7105
7106         return WERR_OK;
7107 }
7108
7109 /****************************************************************************
7110 fill_job_info3
7111 ****************************************************************************/
7112
7113 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7114                              struct spoolss_JobInfo3 *r,
7115                              const print_queue_struct *queue,
7116                              const print_queue_struct *next_queue,
7117                              int position, int snum,
7118                              struct spoolss_PrinterInfo2 *pinfo2)
7119 {
7120         r->job_id               = queue->sysjob;
7121         r->next_job_id          = 0;
7122         if (next_queue) {
7123                 r->next_job_id  = next_queue->sysjob;
7124         }
7125         r->reserved             = 0;
7126
7127         return WERR_OK;
7128 }
7129
7130 /****************************************************************************
7131  Enumjobs at level 1.
7132 ****************************************************************************/
7133
7134 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7135                               const print_queue_struct *queue,
7136                               uint32_t num_queues, int snum,
7137                               struct spoolss_PrinterInfo2 *pinfo2,
7138                               union spoolss_JobInfo **info_p,
7139                               uint32_t *count)
7140 {
7141         union spoolss_JobInfo *info;
7142         int i;
7143         WERROR result = WERR_OK;
7144
7145         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7146         W_ERROR_HAVE_NO_MEMORY(info);
7147
7148         *count = num_queues;
7149
7150         for (i=0; i<*count; i++) {
7151                 result = fill_job_info1(info,
7152                                         &info[i].info1,
7153                                         &queue[i],
7154                                         i,
7155                                         snum,
7156                                         pinfo2);
7157                 if (!W_ERROR_IS_OK(result)) {
7158                         goto out;
7159                 }
7160         }
7161
7162  out:
7163         if (!W_ERROR_IS_OK(result)) {
7164                 TALLOC_FREE(info);
7165                 *count = 0;
7166                 return result;
7167         }
7168
7169         *info_p = info;
7170
7171         return WERR_OK;
7172 }
7173
7174 /****************************************************************************
7175  Enumjobs at level 2.
7176 ****************************************************************************/
7177
7178 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7179                               const print_queue_struct *queue,
7180                               uint32_t num_queues, int snum,
7181                               struct spoolss_PrinterInfo2 *pinfo2,
7182                               union spoolss_JobInfo **info_p,
7183                               uint32_t *count)
7184 {
7185         union spoolss_JobInfo *info;
7186         int i;
7187         WERROR result = WERR_OK;
7188
7189         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7190         W_ERROR_HAVE_NO_MEMORY(info);
7191
7192         *count = num_queues;
7193
7194         for (i=0; i<*count; i++) {
7195                 struct spoolss_DeviceMode *devmode;
7196
7197                 result = spoolss_create_default_devmode(info,
7198                                                         pinfo2->printername,
7199                                                         &devmode);
7200                 if (!W_ERROR_IS_OK(result)) {
7201                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7202                         goto out;
7203                 }
7204
7205                 result = fill_job_info2(info,
7206                                         &info[i].info2,
7207                                         &queue[i],
7208                                         i,
7209                                         snum,
7210                                         pinfo2,
7211                                         devmode);
7212                 if (!W_ERROR_IS_OK(result)) {
7213                         goto out;
7214                 }
7215         }
7216
7217  out:
7218         if (!W_ERROR_IS_OK(result)) {
7219                 TALLOC_FREE(info);
7220                 *count = 0;
7221                 return result;
7222         }
7223
7224         *info_p = info;
7225
7226         return WERR_OK;
7227 }
7228
7229 /****************************************************************************
7230  Enumjobs at level 3.
7231 ****************************************************************************/
7232
7233 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7234                               const print_queue_struct *queue,
7235                               uint32_t num_queues, int snum,
7236                               struct spoolss_PrinterInfo2 *pinfo2,
7237                               union spoolss_JobInfo **info_p,
7238                               uint32_t *count)
7239 {
7240         union spoolss_JobInfo *info;
7241         int i;
7242         WERROR result = WERR_OK;
7243
7244         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7245         W_ERROR_HAVE_NO_MEMORY(info);
7246
7247         *count = num_queues;
7248
7249         for (i=0; i<*count; i++) {
7250                 const print_queue_struct *next_queue = NULL;
7251
7252                 if (i+1 < *count) {
7253                         next_queue = &queue[i+1];
7254                 }
7255
7256                 result = fill_job_info3(info,
7257                                         &info[i].info3,
7258                                         &queue[i],
7259                                         next_queue,
7260                                         i,
7261                                         snum,
7262                                         pinfo2);
7263                 if (!W_ERROR_IS_OK(result)) {
7264                         goto out;
7265                 }
7266         }
7267
7268  out:
7269         if (!W_ERROR_IS_OK(result)) {
7270                 TALLOC_FREE(info);
7271                 *count = 0;
7272                 return result;
7273         }
7274
7275         *info_p = info;
7276
7277         return WERR_OK;
7278 }
7279
7280 /****************************************************************
7281  _spoolss_EnumJobs
7282 ****************************************************************/
7283
7284 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7285                          struct spoolss_EnumJobs *r)
7286 {
7287         WERROR result;
7288         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7289         int snum;
7290         print_status_struct prt_status;
7291         print_queue_struct *queue = NULL;
7292         uint32_t count;
7293
7294         /* that's an [in out] buffer */
7295
7296         if (!r->in.buffer && (r->in.offered != 0)) {
7297                 return WERR_INVALID_PARAM;
7298         }
7299
7300         DEBUG(4,("_spoolss_EnumJobs\n"));
7301
7302         *r->out.needed = 0;
7303         *r->out.count = 0;
7304         *r->out.info = NULL;
7305
7306         /* lookup the printer snum and tdb entry */
7307
7308         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7309                 return WERR_BADFID;
7310         }
7311
7312         result = winreg_get_printer_internal(p->mem_ctx,
7313                                     get_session_info_system(),
7314                                     p->msg_ctx,
7315                                     lp_const_servicename(snum),
7316                                     &pinfo2);
7317         if (!W_ERROR_IS_OK(result)) {
7318                 return result;
7319         }
7320
7321         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7322         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7323                 count, prt_status.status, prt_status.message));
7324
7325         if (count == 0) {
7326                 SAFE_FREE(queue);
7327                 TALLOC_FREE(pinfo2);
7328                 return WERR_OK;
7329         }
7330
7331         switch (r->in.level) {
7332         case 1:
7333                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7334                                          pinfo2, r->out.info, r->out.count);
7335                 break;
7336         case 2:
7337                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7338                                          pinfo2, r->out.info, r->out.count);
7339                 break;
7340         case 3:
7341                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7342                                          pinfo2, r->out.info, r->out.count);
7343                 break;
7344         default:
7345                 result = WERR_UNKNOWN_LEVEL;
7346                 break;
7347         }
7348
7349         SAFE_FREE(queue);
7350         TALLOC_FREE(pinfo2);
7351
7352         if (!W_ERROR_IS_OK(result)) {
7353                 return result;
7354         }
7355
7356         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7357                                                      spoolss_EnumJobs,
7358                                                      *r->out.info, r->in.level,
7359                                                      *r->out.count);
7360         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7361         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7362
7363         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7364 }
7365
7366 /****************************************************************
7367  _spoolss_ScheduleJob
7368 ****************************************************************/
7369
7370 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7371                             struct spoolss_ScheduleJob *r)
7372 {
7373         return WERR_OK;
7374 }
7375
7376 /****************************************************************
7377 ****************************************************************/
7378
7379 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7380                                struct messaging_context *msg_ctx,
7381                                const char *printer_name,
7382                                uint32_t job_id,
7383                                struct spoolss_SetJobInfo1 *r)
7384 {
7385         char *old_doc_name;
7386
7387         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7388                 return WERR_BADFID;
7389         }
7390
7391         if (strequal(old_doc_name, r->document_name)) {
7392                 return WERR_OK;
7393         }
7394
7395         if (!print_job_set_name(server_event_context(), msg_ctx,
7396                                 printer_name, job_id, r->document_name)) {
7397                 return WERR_BADFID;
7398         }
7399
7400         return WERR_OK;
7401 }
7402
7403 /****************************************************************
7404  _spoolss_SetJob
7405 ****************************************************************/
7406
7407 WERROR _spoolss_SetJob(struct pipes_struct *p,
7408                        struct spoolss_SetJob *r)
7409 {
7410         const struct auth_session_info *session_info = p->session_info;
7411         int snum;
7412         WERROR errcode = WERR_BADFUNC;
7413
7414         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7415                 return WERR_BADFID;
7416         }
7417
7418         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7419                 return WERR_INVALID_PRINTER_NAME;
7420         }
7421
7422         switch (r->in.command) {
7423         case SPOOLSS_JOB_CONTROL_CANCEL:
7424         case SPOOLSS_JOB_CONTROL_DELETE:
7425                 errcode = print_job_delete(session_info, p->msg_ctx,
7426                                            snum, r->in.job_id);
7427                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7428                         errcode = WERR_OK;
7429                 }
7430                 break;
7431         case SPOOLSS_JOB_CONTROL_PAUSE:
7432                 errcode = print_job_pause(session_info, p->msg_ctx,
7433                                           snum, r->in.job_id);
7434                 break;
7435         case SPOOLSS_JOB_CONTROL_RESTART:
7436         case SPOOLSS_JOB_CONTROL_RESUME:
7437                 errcode = print_job_resume(session_info, p->msg_ctx,
7438                                            snum, r->in.job_id);
7439                 break;
7440         case 0:
7441                 errcode = WERR_OK;
7442                 break;
7443         default:
7444                 return WERR_UNKNOWN_LEVEL;
7445         }
7446
7447         if (!W_ERROR_IS_OK(errcode)) {
7448                 return errcode;
7449         }
7450
7451         if (r->in.ctr == NULL) {
7452                 return errcode;
7453         }
7454
7455         switch (r->in.ctr->level) {
7456         case 1:
7457                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7458                                            lp_const_servicename(snum),
7459                                            r->in.job_id,
7460                                            r->in.ctr->info.info1);
7461                 break;
7462         case 2:
7463         case 3:
7464         case 4:
7465         default:
7466                 return WERR_UNKNOWN_LEVEL;
7467         }
7468
7469         return errcode;
7470 }
7471
7472 /****************************************************************************
7473  Enumerates all printer drivers by level and architecture.
7474 ****************************************************************************/
7475
7476 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7477                                                        const struct auth_session_info *session_info,
7478                                                        struct messaging_context *msg_ctx,
7479                                                        const char *servername,
7480                                                        const char *architecture,
7481                                                        uint32_t level,
7482                                                        union spoolss_DriverInfo **info_p,
7483                                                        uint32_t *count_p)
7484 {
7485         int i;
7486         uint32_t version;
7487         struct spoolss_DriverInfo8 *driver;
7488         union spoolss_DriverInfo *info = NULL;
7489         uint32_t count = 0;
7490         WERROR result = WERR_OK;
7491         uint32_t num_drivers;
7492         const char **drivers;
7493         struct dcerpc_binding_handle *b;
7494         TALLOC_CTX *tmp_ctx = NULL;
7495
7496         *count_p = 0;
7497         *info_p = NULL;
7498
7499         tmp_ctx = talloc_new(mem_ctx);
7500         if (!tmp_ctx) {
7501                 return WERR_NOMEM;
7502         }
7503
7504         result = winreg_printer_binding_handle(tmp_ctx,
7505                                                session_info,
7506                                                msg_ctx,
7507                                                &b);
7508         if (!W_ERROR_IS_OK(result)) {
7509                 goto out;
7510         }
7511
7512         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7513                 result = winreg_get_driver_list(tmp_ctx, b,
7514                                                 architecture, version,
7515                                                 &num_drivers, &drivers);
7516                 if (!W_ERROR_IS_OK(result)) {
7517                         goto out;
7518                 }
7519                 DEBUG(4, ("we have:[%d] drivers in environment"
7520                           " [%s] and version [%d]\n",
7521                           num_drivers, architecture, version));
7522
7523                 if (num_drivers != 0) {
7524                         info = talloc_realloc(tmp_ctx, info,
7525                                                     union spoolss_DriverInfo,
7526                                                     count + num_drivers);
7527                         if (!info) {
7528                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7529                                         "failed to enlarge driver info buffer!\n"));
7530                                 result = WERR_NOMEM;
7531                                 goto out;
7532                         }
7533                 }
7534
7535                 for (i = 0; i < num_drivers; i++) {
7536                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7537
7538                         result = winreg_get_driver(tmp_ctx, b,
7539                                                    architecture, drivers[i],
7540                                                    version, &driver);
7541                         if (!W_ERROR_IS_OK(result)) {
7542                                 goto out;
7543                         }
7544
7545                         switch (level) {
7546                         case 1:
7547                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7548                                                                    driver, servername);
7549                                 break;
7550                         case 2:
7551                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7552                                                                    driver, servername);
7553                                 break;
7554                         case 3:
7555                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7556                                                                    driver, servername);
7557                                 break;
7558                         case 4:
7559                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7560                                                                    driver, servername);
7561                                 break;
7562                         case 5:
7563                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7564                                                                    driver, servername);
7565                                 break;
7566                         case 6:
7567                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7568                                                                    driver, servername);
7569                                 break;
7570                         case 8:
7571                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7572                                                                    driver, servername);
7573                                 break;
7574                         default:
7575                                 result = WERR_UNKNOWN_LEVEL;
7576                                 break;
7577                         }
7578
7579                         TALLOC_FREE(driver);
7580
7581                         if (!W_ERROR_IS_OK(result)) {
7582                                 goto out;
7583                         }
7584                 }
7585
7586                 count += num_drivers;
7587                 TALLOC_FREE(drivers);
7588         }
7589
7590 out:
7591         if (W_ERROR_IS_OK(result)) {
7592                 *info_p = talloc_move(mem_ctx, &info);
7593                 *count_p = count;
7594         }
7595
7596         talloc_free(tmp_ctx);
7597         return result;
7598 }
7599
7600 /****************************************************************************
7601  Enumerates all printer drivers by level.
7602 ****************************************************************************/
7603
7604 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7605                                        const struct auth_session_info *session_info,
7606                                        struct messaging_context *msg_ctx,
7607                                        const char *servername,
7608                                        const char *architecture,
7609                                        uint32_t level,
7610                                        union spoolss_DriverInfo **info_p,
7611                                        uint32_t *count_p)
7612 {
7613         uint32_t a,i;
7614         WERROR result = WERR_OK;
7615
7616         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7617
7618                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7619
7620                         union spoolss_DriverInfo *info = NULL;
7621                         uint32_t count = 0;
7622
7623                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7624                                                                           session_info,
7625                                                                           msg_ctx,
7626                                                                           servername,
7627                                                                           archi_table[a].long_archi,
7628                                                                           level,
7629                                                                           &info,
7630                                                                           &count);
7631                         if (!W_ERROR_IS_OK(result)) {
7632                                 continue;
7633                         }
7634
7635                         for (i=0; i < count; i++) {
7636                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7637                                              info[i], info_p, count_p);
7638                         }
7639                 }
7640
7641                 return result;
7642         }
7643
7644         return enumprinterdrivers_level_by_architecture(mem_ctx,
7645                                                         session_info,
7646                                                         msg_ctx,
7647                                                         servername,
7648                                                         architecture,
7649                                                         level,
7650                                                         info_p,
7651                                                         count_p);
7652 }
7653
7654 /****************************************************************
7655  _spoolss_EnumPrinterDrivers
7656 ****************************************************************/
7657
7658 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7659                                    struct spoolss_EnumPrinterDrivers *r)
7660 {
7661         const char *cservername;
7662         WERROR result;
7663
7664         /* that's an [in out] buffer */
7665
7666         if (!r->in.buffer && (r->in.offered != 0)) {
7667                 return WERR_INVALID_PARAM;
7668         }
7669
7670         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7671
7672         *r->out.needed = 0;
7673         *r->out.count = 0;
7674         *r->out.info = NULL;
7675
7676         cservername = canon_servername(r->in.server);
7677
7678         if (!is_myname_or_ipaddr(cservername)) {
7679                 return WERR_UNKNOWN_PRINTER_DRIVER;
7680         }
7681
7682         result = enumprinterdrivers_level(p->mem_ctx,
7683                                           get_session_info_system(),
7684                                           p->msg_ctx,
7685                                           cservername,
7686                                           r->in.environment,
7687                                           r->in.level,
7688                                           r->out.info,
7689                                           r->out.count);
7690         if (!W_ERROR_IS_OK(result)) {
7691                 return result;
7692         }
7693
7694         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7695                                                      spoolss_EnumPrinterDrivers,
7696                                                      *r->out.info, r->in.level,
7697                                                      *r->out.count);
7698         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7699         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7700
7701         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7702 }
7703
7704 /****************************************************************
7705  _spoolss_EnumForms
7706 ****************************************************************/
7707
7708 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7709                           struct spoolss_EnumForms *r)
7710 {
7711         WERROR result;
7712
7713         *r->out.count = 0;
7714         *r->out.needed = 0;
7715         *r->out.info = NULL;
7716
7717         /* that's an [in out] buffer */
7718
7719         if (!r->in.buffer && (r->in.offered != 0) ) {
7720                 return WERR_INVALID_PARAM;
7721         }
7722
7723         DEBUG(4,("_spoolss_EnumForms\n"));
7724         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7725         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7726
7727         switch (r->in.level) {
7728         case 1:
7729                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7730                                                    get_session_info_system(),
7731                                                    p->msg_ctx,
7732                                                    r->out.count,
7733                                                    r->out.info);
7734                 break;
7735         default:
7736                 result = WERR_UNKNOWN_LEVEL;
7737                 break;
7738         }
7739
7740         if (!W_ERROR_IS_OK(result)) {
7741                 return result;
7742         }
7743
7744         if (*r->out.count == 0) {
7745                 return WERR_NO_MORE_ITEMS;
7746         }
7747
7748         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7749                                                      spoolss_EnumForms,
7750                                                      *r->out.info, r->in.level,
7751                                                      *r->out.count);
7752         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7753         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7754
7755         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7756 }
7757
7758 /****************************************************************
7759  _spoolss_GetForm
7760 ****************************************************************/
7761
7762 WERROR _spoolss_GetForm(struct pipes_struct *p,
7763                         struct spoolss_GetForm *r)
7764 {
7765         WERROR result;
7766
7767         /* that's an [in out] buffer */
7768
7769         if (!r->in.buffer && (r->in.offered != 0)) {
7770                 return WERR_INVALID_PARAM;
7771         }
7772
7773         DEBUG(4,("_spoolss_GetForm\n"));
7774         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7775         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7776
7777         switch (r->in.level) {
7778         case 1:
7779                 result = winreg_printer_getform1_internal(p->mem_ctx,
7780                                                  get_session_info_system(),
7781                                                  p->msg_ctx,
7782                                                  r->in.form_name,
7783                                                  &r->out.info->info1);
7784                 break;
7785         default:
7786                 result = WERR_UNKNOWN_LEVEL;
7787                 break;
7788         }
7789
7790         if (!W_ERROR_IS_OK(result)) {
7791                 TALLOC_FREE(r->out.info);
7792                 return result;
7793         }
7794
7795         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7796                                                r->out.info, r->in.level);
7797         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7798
7799         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7800 }
7801
7802 /****************************************************************************
7803 ****************************************************************************/
7804
7805 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7806                           struct spoolss_PortInfo1 *r,
7807                           const char *name)
7808 {
7809         r->port_name = talloc_strdup(mem_ctx, name);
7810         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7811
7812         return WERR_OK;
7813 }
7814
7815 /****************************************************************************
7816  TODO: This probably needs distinguish between TCP/IP and Local ports
7817  somehow.
7818 ****************************************************************************/
7819
7820 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7821                           struct spoolss_PortInfo2 *r,
7822                           const char *name)
7823 {
7824         r->port_name = talloc_strdup(mem_ctx, name);
7825         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7826
7827         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7828         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7829
7830         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7831         W_ERROR_HAVE_NO_MEMORY(r->description);
7832
7833         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7834         r->reserved = 0;
7835
7836         return WERR_OK;
7837 }
7838
7839
7840 /****************************************************************************
7841  wrapper around the enumer ports command
7842 ****************************************************************************/
7843
7844 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7845 {
7846         char *cmd = lp_enumports_cmd(talloc_tos());
7847         char **qlines = NULL;
7848         char *command = NULL;
7849         int numlines;
7850         int ret;
7851         int fd;
7852
7853         *count = 0;
7854         *lines = NULL;
7855
7856         /* if no hook then just fill in the default port */
7857
7858         if ( !*cmd ) {
7859                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7860                         return WERR_NOMEM;
7861                 }
7862                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7863                         TALLOC_FREE(qlines);
7864                         return WERR_NOMEM;
7865                 }
7866                 qlines[1] = NULL;
7867                 numlines = 1;
7868         }
7869         else {
7870                 /* we have a valid enumport command */
7871
7872                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7873                 if (!command) {
7874                         return WERR_NOMEM;
7875                 }
7876
7877                 DEBUG(10,("Running [%s]\n", command));
7878                 ret = smbrun(command, &fd);
7879                 DEBUG(10,("Returned [%d]\n", ret));
7880                 TALLOC_FREE(command);
7881                 if (ret != 0) {
7882                         if (fd != -1) {
7883                                 close(fd);
7884                         }
7885                         return WERR_ACCESS_DENIED;
7886                 }
7887
7888                 numlines = 0;
7889                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7890                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7891                 close(fd);
7892         }
7893
7894         *count = numlines;
7895         *lines = qlines;
7896
7897         return WERR_OK;
7898 }
7899
7900 /****************************************************************************
7901  enumports level 1.
7902 ****************************************************************************/
7903
7904 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7905                                 union spoolss_PortInfo **info_p,
7906                                 uint32_t *count)
7907 {
7908         union spoolss_PortInfo *info = NULL;
7909         int i=0;
7910         WERROR result = WERR_OK;
7911         char **qlines = NULL;
7912         int numlines = 0;
7913
7914         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7915         if (!W_ERROR_IS_OK(result)) {
7916                 goto out;
7917         }
7918
7919         if (numlines) {
7920                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7921                 if (!info) {
7922                         DEBUG(10,("Returning WERR_NOMEM\n"));
7923                         result = WERR_NOMEM;
7924                         goto out;
7925                 }
7926
7927                 for (i=0; i<numlines; i++) {
7928                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7929                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7930                         if (!W_ERROR_IS_OK(result)) {
7931                                 goto out;
7932                         }
7933                 }
7934         }
7935         TALLOC_FREE(qlines);
7936
7937 out:
7938         if (!W_ERROR_IS_OK(result)) {
7939                 TALLOC_FREE(info);
7940                 TALLOC_FREE(qlines);
7941                 *count = 0;
7942                 *info_p = NULL;
7943                 return result;
7944         }
7945
7946         *info_p = info;
7947         *count = numlines;
7948
7949         return WERR_OK;
7950 }
7951
7952 /****************************************************************************
7953  enumports level 2.
7954 ****************************************************************************/
7955
7956 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7957                                 union spoolss_PortInfo **info_p,
7958                                 uint32_t *count)
7959 {
7960         union spoolss_PortInfo *info = NULL;
7961         int i=0;
7962         WERROR result = WERR_OK;
7963         char **qlines = NULL;
7964         int numlines = 0;
7965
7966         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7967         if (!W_ERROR_IS_OK(result)) {
7968                 goto out;
7969         }
7970
7971         if (numlines) {
7972                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7973                 if (!info) {
7974                         DEBUG(10,("Returning WERR_NOMEM\n"));
7975                         result = WERR_NOMEM;
7976                         goto out;
7977                 }
7978
7979                 for (i=0; i<numlines; i++) {
7980                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7981                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7982                         if (!W_ERROR_IS_OK(result)) {
7983                                 goto out;
7984                         }
7985                 }
7986         }
7987         TALLOC_FREE(qlines);
7988
7989 out:
7990         if (!W_ERROR_IS_OK(result)) {
7991                 TALLOC_FREE(info);
7992                 TALLOC_FREE(qlines);
7993                 *count = 0;
7994                 *info_p = NULL;
7995                 return result;
7996         }
7997
7998         *info_p = info;
7999         *count = numlines;
8000
8001         return WERR_OK;
8002 }
8003
8004 /****************************************************************
8005  _spoolss_EnumPorts
8006 ****************************************************************/
8007
8008 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8009                           struct spoolss_EnumPorts *r)
8010 {
8011         WERROR result;
8012
8013         /* that's an [in out] buffer */
8014
8015         if (!r->in.buffer && (r->in.offered != 0)) {
8016                 return WERR_INVALID_PARAM;
8017         }
8018
8019         DEBUG(4,("_spoolss_EnumPorts\n"));
8020
8021         *r->out.count = 0;
8022         *r->out.needed = 0;
8023         *r->out.info = NULL;
8024
8025         switch (r->in.level) {
8026         case 1:
8027                 result = enumports_level_1(p->mem_ctx, r->out.info,
8028                                            r->out.count);
8029                 break;
8030         case 2:
8031                 result = enumports_level_2(p->mem_ctx, r->out.info,
8032                                            r->out.count);
8033                 break;
8034         default:
8035                 return WERR_UNKNOWN_LEVEL;
8036         }
8037
8038         if (!W_ERROR_IS_OK(result)) {
8039                 return result;
8040         }
8041
8042         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8043                                                      spoolss_EnumPorts,
8044                                                      *r->out.info, r->in.level,
8045                                                      *r->out.count);
8046         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8047         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8048
8049         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8050 }
8051
8052 /****************************************************************************
8053 ****************************************************************************/
8054
8055 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8056                                            const char *server,
8057                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8058                                            struct spoolss_DeviceMode *devmode,
8059                                            struct security_descriptor *secdesc,
8060                                            struct spoolss_UserLevelCtr *user_ctr,
8061                                            struct policy_handle *handle)
8062 {
8063         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8064         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8065         int     snum;
8066         WERROR err = WERR_OK;
8067
8068         /* samba does not have a concept of local, non-shared printers yet, so
8069          * make sure we always setup sharename - gd */
8070         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8071             (info2->printername != NULL && info2->printername[0] != '\0')) {
8072                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8073                         "no sharename has been set, setting printername %s as sharename\n",
8074                         info2->printername));
8075                 info2->sharename = info2->printername;
8076         }
8077
8078         /* check to see if the printer already exists */
8079         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8080                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8081                         info2->sharename));
8082                 return WERR_PRINTER_ALREADY_EXISTS;
8083         }
8084
8085         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8086                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8087                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8088                                 info2->printername));
8089                         return WERR_PRINTER_ALREADY_EXISTS;
8090                 }
8091         }
8092
8093         /* validate printer info struct */
8094         if (!info2->printername || strlen(info2->printername) == 0) {
8095                 return WERR_INVALID_PRINTER_NAME;
8096         }
8097         if (!info2->portname || strlen(info2->portname) == 0) {
8098                 return WERR_UNKNOWN_PORT;
8099         }
8100         if (!info2->drivername || strlen(info2->drivername) == 0) {
8101                 return WERR_UNKNOWN_PRINTER_DRIVER;
8102         }
8103         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8104                 return WERR_UNKNOWN_PRINTPROCESSOR;
8105         }
8106
8107         /* FIXME!!!  smbd should check to see if the driver is installed before
8108            trying to add a printer like this  --jerry */
8109
8110         if (*lp_addprinter_cmd(talloc_tos()) ) {
8111                 char *raddr;
8112
8113                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8114                                                          p->mem_ctx);
8115                 if (raddr == NULL) {
8116                         return WERR_NOMEM;
8117                 }
8118
8119                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8120                                        info2, raddr,
8121                                        p->msg_ctx) ) {
8122                         return WERR_ACCESS_DENIED;
8123                 }
8124         } else {
8125                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8126                         "smb.conf parameter \"addprinter command\" is defined. This "
8127                         "parameter must exist for this call to succeed\n",
8128                         info2->sharename ));
8129         }
8130
8131         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8132                 return WERR_ACCESS_DENIED;
8133         }
8134
8135         /* you must be a printer admin to add a new printer */
8136         if (!print_access_check(p->session_info,
8137                                 p->msg_ctx,
8138                                 snum,
8139                                 PRINTER_ACCESS_ADMINISTER)) {
8140                 return WERR_ACCESS_DENIED;
8141         }
8142
8143         /*
8144          * Do sanity check on the requested changes for Samba.
8145          */
8146
8147         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8148                 return WERR_INVALID_PARAM;
8149         }
8150
8151         if (devmode == NULL) {
8152                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8153         }
8154
8155         err = update_dsspooler(p->mem_ctx,
8156                                get_session_info_system(),
8157                                p->msg_ctx,
8158                                0,
8159                                info2,
8160                                NULL);
8161         if (!W_ERROR_IS_OK(err)) {
8162                 return err;
8163         }
8164
8165         err = winreg_update_printer_internal(p->mem_ctx,
8166                                     get_session_info_system(),
8167                                     p->msg_ctx,
8168                                     info2->sharename,
8169                                     info2_mask,
8170                                     info2,
8171                                     devmode,
8172                                     secdesc);
8173         if (!W_ERROR_IS_OK(err)) {
8174                 return err;
8175         }
8176
8177         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8178         if (!W_ERROR_IS_OK(err)) {
8179                 /* Handle open failed - remove addition. */
8180                 ZERO_STRUCTP(handle);
8181                 return err;
8182         }
8183
8184         return WERR_OK;
8185 }
8186
8187 /****************************************************************
8188  _spoolss_AddPrinterEx
8189 ****************************************************************/
8190
8191 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8192                              struct spoolss_AddPrinterEx *r)
8193 {
8194         switch (r->in.info_ctr->level) {
8195         case 1:
8196                 /* we don't handle yet */
8197                 /* but I know what to do ... */
8198                 return WERR_UNKNOWN_LEVEL;
8199         case 2:
8200                 return spoolss_addprinterex_level_2(p, r->in.server,
8201                                                     r->in.info_ctr,
8202                                                     r->in.devmode_ctr->devmode,
8203                                                     r->in.secdesc_ctr->sd,
8204                                                     r->in.userlevel_ctr,
8205                                                     r->out.handle);
8206         default:
8207                 return WERR_UNKNOWN_LEVEL;
8208         }
8209 }
8210
8211 /****************************************************************
8212  _spoolss_AddPrinter
8213 ****************************************************************/
8214
8215 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8216                            struct spoolss_AddPrinter *r)
8217 {
8218         struct spoolss_AddPrinterEx a;
8219         struct spoolss_UserLevelCtr userlevel_ctr;
8220
8221         ZERO_STRUCT(userlevel_ctr);
8222
8223         userlevel_ctr.level = 1;
8224
8225         a.in.server             = r->in.server;
8226         a.in.info_ctr           = r->in.info_ctr;
8227         a.in.devmode_ctr        = r->in.devmode_ctr;
8228         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8229         a.in.userlevel_ctr      = &userlevel_ctr;
8230         a.out.handle            = r->out.handle;
8231
8232         return _spoolss_AddPrinterEx(p, &a);
8233 }
8234
8235 /****************************************************************
8236  _spoolss_AddPrinterDriverEx
8237 ****************************************************************/
8238
8239 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8240                                    struct spoolss_AddPrinterDriverEx *r)
8241 {
8242         WERROR err = WERR_OK;
8243         const char *driver_name = NULL;
8244         uint32_t version;
8245         const char *fn;
8246
8247         switch (p->opnum) {
8248                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8249                         fn = "_spoolss_AddPrinterDriver";
8250                         break;
8251                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8252                         fn = "_spoolss_AddPrinterDriverEx";
8253                         break;
8254                 default:
8255                         return WERR_INVALID_PARAM;
8256         }
8257
8258         /*
8259          * we only support the semantics of AddPrinterDriver()
8260          * i.e. only copy files that are newer than existing ones
8261          */
8262
8263         if (r->in.flags == 0) {
8264                 return WERR_INVALID_PARAM;
8265         }
8266
8267         if (r->in.flags != APD_COPY_NEW_FILES) {
8268                 return WERR_ACCESS_DENIED;
8269         }
8270
8271         /* FIXME */
8272         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8273                 /* Clever hack from Martin Zielinski <mz@seh.de>
8274                  * to allow downgrade from level 8 (Vista).
8275                  */
8276                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8277                         r->in.info_ctr->level));
8278                 return WERR_UNKNOWN_LEVEL;
8279         }
8280
8281         DEBUG(5,("Cleaning driver's information\n"));
8282         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8283         if (!W_ERROR_IS_OK(err))
8284                 goto done;
8285
8286         DEBUG(5,("Moving driver to final destination\n"));
8287         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8288         if (!W_ERROR_IS_OK(err)) {
8289                 goto done;
8290         }
8291
8292         err = winreg_add_driver_internal(p->mem_ctx,
8293                                 get_session_info_system(),
8294                                 p->msg_ctx,
8295                                 r->in.info_ctr,
8296                                 &driver_name,
8297                                 &version);
8298         if (!W_ERROR_IS_OK(err)) {
8299                 goto done;
8300         }
8301
8302         /*
8303          * I think this is where he DrvUpgradePrinter() hook would be
8304          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8305          * server.  Right now, we just need to send ourselves a message
8306          * to update each printer bound to this driver.   --jerry
8307          */
8308
8309         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8310                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8311                         fn, driver_name));
8312         }
8313
8314 done:
8315         return err;
8316 }
8317
8318 /****************************************************************
8319  _spoolss_AddPrinterDriver
8320 ****************************************************************/
8321
8322 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8323                                  struct spoolss_AddPrinterDriver *r)
8324 {
8325         struct spoolss_AddPrinterDriverEx a;
8326
8327         switch (r->in.info_ctr->level) {
8328         case 2:
8329         case 3:
8330         case 4:
8331         case 5:
8332                 break;
8333         default:
8334                 return WERR_UNKNOWN_LEVEL;
8335         }
8336
8337         a.in.servername         = r->in.servername;
8338         a.in.info_ctr           = r->in.info_ctr;
8339         a.in.flags              = APD_COPY_NEW_FILES;
8340
8341         return _spoolss_AddPrinterDriverEx(p, &a);
8342 }
8343
8344 /****************************************************************************
8345 ****************************************************************************/
8346
8347 struct _spoolss_paths {
8348         int type;
8349         const char *share;
8350         const char *dir;
8351 };
8352
8353 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8354
8355 static const struct _spoolss_paths spoolss_paths[]= {
8356         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8357         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8358 };
8359
8360 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8361                                           const char *servername,
8362                                           const char *environment,
8363                                           int component,
8364                                           char **path)
8365 {
8366         const char *pservername = NULL;
8367         const char *long_archi;
8368         const char *short_archi;
8369
8370         *path = NULL;
8371
8372         /* environment may be empty */
8373         if (environment && strlen(environment)) {
8374                 long_archi = environment;
8375         } else {
8376                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8377                                                   "spoolss", "architecture",
8378                                                   SPOOLSS_ARCHITECTURE_NT_X86);
8379         }
8380
8381         /* servername may be empty */
8382         if (servername && strlen(servername)) {
8383                 pservername = canon_servername(servername);
8384
8385                 if (!is_myname_or_ipaddr(pservername)) {
8386                         return WERR_INVALID_PARAM;
8387                 }
8388         }
8389
8390         if (!(short_archi = get_short_archi(long_archi))) {
8391                 return WERR_INVALID_ENVIRONMENT;
8392         }
8393
8394         switch (component) {
8395         case SPOOLSS_PRTPROCS_PATH:
8396         case SPOOLSS_DRIVER_PATH:
8397                 if (pservername) {
8398                         *path = talloc_asprintf(mem_ctx,
8399                                         "\\\\%s\\%s\\%s",
8400                                         pservername,
8401                                         spoolss_paths[component].share,
8402                                         short_archi);
8403                 } else {
8404                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8405                                         SPOOLSS_DEFAULT_SERVER_PATH,
8406                                         spoolss_paths[component].dir,
8407                                         short_archi);
8408                 }
8409                 break;
8410         default:
8411                 return WERR_INVALID_PARAM;
8412         }
8413
8414         if (!*path) {
8415                 return WERR_NOMEM;
8416         }
8417
8418         return WERR_OK;
8419 }
8420
8421 /****************************************************************************
8422 ****************************************************************************/
8423
8424 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8425                                           const char *servername,
8426                                           const char *environment,
8427                                           struct spoolss_DriverDirectoryInfo1 *r)
8428 {
8429         WERROR werr;
8430         char *path = NULL;
8431
8432         werr = compose_spoolss_server_path(mem_ctx,
8433                                            servername,
8434                                            environment,
8435                                            SPOOLSS_DRIVER_PATH,
8436                                            &path);
8437         if (!W_ERROR_IS_OK(werr)) {
8438                 return werr;
8439         }
8440
8441         DEBUG(4,("printer driver directory: [%s]\n", path));
8442
8443         r->directory_name = path;
8444
8445         return WERR_OK;
8446 }
8447
8448 /****************************************************************
8449  _spoolss_GetPrinterDriverDirectory
8450 ****************************************************************/
8451
8452 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8453                                           struct spoolss_GetPrinterDriverDirectory *r)
8454 {
8455         WERROR werror;
8456
8457         /* that's an [in out] buffer */
8458
8459         if (!r->in.buffer && (r->in.offered != 0)) {
8460                 return WERR_INVALID_PARAM;
8461         }
8462
8463         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8464                 r->in.level));
8465
8466         *r->out.needed = 0;
8467
8468         /* r->in.level is ignored */
8469
8470         werror = getprinterdriverdir_level_1(p->mem_ctx,
8471                                              r->in.server,
8472                                              r->in.environment,
8473                                              &r->out.info->info1);
8474         if (!W_ERROR_IS_OK(werror)) {
8475                 TALLOC_FREE(r->out.info);
8476                 return werror;
8477         }
8478
8479         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8480                                                r->out.info, r->in.level);
8481         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8482
8483         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8484 }
8485
8486 /****************************************************************
8487  _spoolss_EnumPrinterData
8488 ****************************************************************/
8489
8490 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8491                                 struct spoolss_EnumPrinterData *r)
8492 {
8493         WERROR result;
8494         struct spoolss_EnumPrinterDataEx r2;
8495         uint32_t count;
8496         struct spoolss_PrinterEnumValues *info, *val = NULL;
8497         uint32_t needed;
8498
8499         r2.in.handle    = r->in.handle;
8500         r2.in.key_name  = "PrinterDriverData";
8501         r2.in.offered   = 0;
8502         r2.out.count    = &count;
8503         r2.out.info     = &info;
8504         r2.out.needed   = &needed;
8505
8506         result = _spoolss_EnumPrinterDataEx(p, &r2);
8507         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8508                 r2.in.offered = needed;
8509                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8510         }
8511         if (!W_ERROR_IS_OK(result)) {
8512                 return result;
8513         }
8514
8515         /*
8516          * The NT machine wants to know the biggest size of value and data
8517          *
8518          * cf: MSDN EnumPrinterData remark section
8519          */
8520
8521         if (!r->in.value_offered && !r->in.data_offered) {
8522                 uint32_t biggest_valuesize = 0;
8523                 uint32_t biggest_datasize = 0;
8524                 int i, name_length;
8525
8526                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8527
8528                 for (i=0; i<count; i++) {
8529
8530                         name_length = strlen(info[i].value_name);
8531                         if (strlen(info[i].value_name) > biggest_valuesize) {
8532                                 biggest_valuesize = name_length;
8533                         }
8534
8535                         if (info[i].data_length > biggest_datasize) {
8536                                 biggest_datasize = info[i].data_length;
8537                         }
8538
8539                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8540                                 biggest_datasize));
8541                 }
8542
8543                 /* the value is an UNICODE string but real_value_size is the length
8544                    in bytes including the trailing 0 */
8545
8546                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8547                 *r->out.data_needed  = biggest_datasize;
8548
8549                 DEBUG(6,("final values: [%d], [%d]\n",
8550                         *r->out.value_needed, *r->out.data_needed));
8551
8552                 return WERR_OK;
8553         }
8554
8555         if (r->in.enum_index < count) {
8556                 val = &info[r->in.enum_index];
8557         }
8558
8559         if (val == NULL) {
8560                 /* out_value should default to "" or else NT4 has
8561                    problems unmarshalling the response */
8562
8563                 if (r->in.value_offered) {
8564                         *r->out.value_needed = 1;
8565                         r->out.value_name = talloc_strdup(r, "");
8566                         if (!r->out.value_name) {
8567                                 return WERR_NOMEM;
8568                         }
8569                 } else {
8570                         r->out.value_name = NULL;
8571                         *r->out.value_needed = 0;
8572                 }
8573
8574                 /* the data is counted in bytes */
8575
8576                 *r->out.data_needed = r->in.data_offered;
8577
8578                 result = WERR_NO_MORE_ITEMS;
8579         } else {
8580                 /*
8581                  * the value is:
8582                  * - counted in bytes in the request
8583                  * - counted in UNICODE chars in the max reply
8584                  * - counted in bytes in the real size
8585                  *
8586                  * take a pause *before* coding not *during* coding
8587                  */
8588
8589                 /* name */
8590                 if (r->in.value_offered) {
8591                         r->out.value_name = talloc_strdup(r, val->value_name);
8592                         if (!r->out.value_name) {
8593                                 return WERR_NOMEM;
8594                         }
8595                         *r->out.value_needed = val->value_name_len;
8596                 } else {
8597                         r->out.value_name = NULL;
8598                         *r->out.value_needed = 0;
8599                 }
8600
8601                 /* type */
8602
8603                 *r->out.type = val->type;
8604
8605                 /* data - counted in bytes */
8606
8607                 /*
8608                  * See the section "Dynamically Typed Query Parameters"
8609                  * in MS-RPRN.
8610                  */
8611
8612                 if (r->out.data && val->data && val->data->data &&
8613                                 val->data_length && r->in.data_offered) {
8614                         memcpy(r->out.data, val->data->data,
8615                                 MIN(val->data_length,r->in.data_offered));
8616                 }
8617
8618                 *r->out.data_needed = val->data_length;
8619
8620                 result = WERR_OK;
8621         }
8622
8623         return result;
8624 }
8625
8626 /****************************************************************
8627  _spoolss_SetPrinterData
8628 ****************************************************************/
8629
8630 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8631                                struct spoolss_SetPrinterData *r)
8632 {
8633         struct spoolss_SetPrinterDataEx r2;
8634
8635         r2.in.handle            = r->in.handle;
8636         r2.in.key_name          = "PrinterDriverData";
8637         r2.in.value_name        = r->in.value_name;
8638         r2.in.type              = r->in.type;
8639         r2.in.data              = r->in.data;
8640         r2.in.offered           = r->in.offered;
8641
8642         return _spoolss_SetPrinterDataEx(p, &r2);
8643 }
8644
8645 /****************************************************************
8646  _spoolss_ResetPrinter
8647 ****************************************************************/
8648
8649 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8650                              struct spoolss_ResetPrinter *r)
8651 {
8652         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8653         int             snum;
8654
8655         DEBUG(5,("_spoolss_ResetPrinter\n"));
8656
8657         /*
8658          * All we do is to check to see if the handle and queue is valid.
8659          * This call really doesn't mean anything to us because we only
8660          * support RAW printing.   --jerry
8661          */
8662
8663         if (!Printer) {
8664                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8665                         OUR_HANDLE(r->in.handle)));
8666                 return WERR_BADFID;
8667         }
8668
8669         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8670                 return WERR_BADFID;
8671
8672
8673         /* blindly return success */
8674         return WERR_OK;
8675 }
8676
8677 /****************************************************************
8678  _spoolss_DeletePrinterData
8679 ****************************************************************/
8680
8681 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8682                                   struct spoolss_DeletePrinterData *r)
8683 {
8684         struct spoolss_DeletePrinterDataEx r2;
8685
8686         r2.in.handle            = r->in.handle;
8687         r2.in.key_name          = "PrinterDriverData";
8688         r2.in.value_name        = r->in.value_name;
8689
8690         return _spoolss_DeletePrinterDataEx(p, &r2);
8691 }
8692
8693 /****************************************************************
8694  _spoolss_AddForm
8695 ****************************************************************/
8696
8697 WERROR _spoolss_AddForm(struct pipes_struct *p,
8698                         struct spoolss_AddForm *r)
8699 {
8700         struct spoolss_AddFormInfo1 *form;
8701         int snum = -1;
8702         WERROR status = WERR_OK;
8703         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8704         struct dcerpc_binding_handle *b;
8705         TALLOC_CTX *tmp_ctx = NULL;
8706
8707         DEBUG(5,("_spoolss_AddForm\n"));
8708
8709         if (!Printer) {
8710                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8711                         OUR_HANDLE(r->in.handle)));
8712                 return WERR_BADFID;
8713         }
8714
8715         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8716            and not a printer admin, then fail */
8717
8718         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8719             !security_token_has_privilege(p->session_info->security_token,
8720                                           SEC_PRIV_PRINT_OPERATOR)) {
8721                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8722                 return WERR_ACCESS_DENIED;
8723         }
8724
8725         if (r->in.info_ctr->level != 1) {
8726                 return WERR_INVALID_LEVEL;
8727         }
8728
8729         form = r->in.info_ctr->info.info1;
8730         if (!form) {
8731                 return WERR_INVALID_PARAM;
8732         }
8733
8734         switch (form->flags) {
8735         case SPOOLSS_FORM_USER:
8736         case SPOOLSS_FORM_BUILTIN:
8737         case SPOOLSS_FORM_PRINTER:
8738                 break;
8739         default:
8740                 return WERR_INVALID_PARAM;
8741         }
8742
8743         tmp_ctx = talloc_new(p->mem_ctx);
8744         if (!tmp_ctx) {
8745                 return WERR_NOMEM;
8746         }
8747
8748         status = winreg_printer_binding_handle(tmp_ctx,
8749                                                get_session_info_system(),
8750                                                p->msg_ctx,
8751                                                &b);
8752         if (!W_ERROR_IS_OK(status)) {
8753                 goto done;
8754         }
8755
8756         status = winreg_printer_addform1(tmp_ctx, b, form);
8757         if (!W_ERROR_IS_OK(status)) {
8758                 goto done;
8759         }
8760
8761         /*
8762          * ChangeID must always be set if this is a printer
8763          */
8764         if (Printer->printer_type == SPLHND_PRINTER) {
8765                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8766                         status = WERR_BADFID;
8767                         goto done;
8768                 }
8769
8770                 status = winreg_printer_update_changeid(tmp_ctx, b,
8771                                                         lp_const_servicename(snum));
8772         }
8773
8774 done:
8775         talloc_free(tmp_ctx);
8776         return status;
8777 }
8778
8779 /****************************************************************
8780  _spoolss_DeleteForm
8781 ****************************************************************/
8782
8783 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8784                            struct spoolss_DeleteForm *r)
8785 {
8786         const char *form_name = r->in.form_name;
8787         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8788         int snum = -1;
8789         WERROR status = WERR_OK;
8790         struct dcerpc_binding_handle *b;
8791         TALLOC_CTX *tmp_ctx = NULL;
8792
8793         DEBUG(5,("_spoolss_DeleteForm\n"));
8794
8795         if (!Printer) {
8796                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8797                         OUR_HANDLE(r->in.handle)));
8798                 return WERR_BADFID;
8799         }
8800
8801         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8802             !security_token_has_privilege(p->session_info->security_token,
8803                                           SEC_PRIV_PRINT_OPERATOR)) {
8804                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8805                 return WERR_ACCESS_DENIED;
8806         }
8807
8808         tmp_ctx = talloc_new(p->mem_ctx);
8809         if (!tmp_ctx) {
8810                 return WERR_NOMEM;
8811         }
8812
8813         status = winreg_printer_binding_handle(tmp_ctx,
8814                                                get_session_info_system(),
8815                                                p->msg_ctx,
8816                                                &b);
8817         if (!W_ERROR_IS_OK(status)) {
8818                 goto done;
8819         }
8820
8821         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8822         if (!W_ERROR_IS_OK(status)) {
8823                 goto done;
8824         }
8825
8826         /*
8827          * ChangeID must always be set if this is a printer
8828          */
8829         if (Printer->printer_type == SPLHND_PRINTER) {
8830                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8831                         status = WERR_BADFID;
8832                         goto done;
8833                 }
8834
8835                 status = winreg_printer_update_changeid(tmp_ctx, b,
8836                                                         lp_const_servicename(snum));
8837         }
8838
8839 done:
8840         talloc_free(tmp_ctx);
8841         return status;
8842 }
8843
8844 /****************************************************************
8845  _spoolss_SetForm
8846 ****************************************************************/
8847
8848 WERROR _spoolss_SetForm(struct pipes_struct *p,
8849                         struct spoolss_SetForm *r)
8850 {
8851         struct spoolss_AddFormInfo1 *form;
8852         const char *form_name = r->in.form_name;
8853         int snum = -1;
8854         WERROR status = WERR_OK;
8855         struct dcerpc_binding_handle *b;
8856         TALLOC_CTX *tmp_ctx = NULL;
8857
8858         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8859
8860         DEBUG(5,("_spoolss_SetForm\n"));
8861
8862         if (!Printer) {
8863                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8864                         OUR_HANDLE(r->in.handle)));
8865                 return WERR_BADFID;
8866         }
8867
8868         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8869            and not a printer admin, then fail */
8870
8871         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8872              !security_token_has_privilege(p->session_info->security_token,
8873                                            SEC_PRIV_PRINT_OPERATOR)) {
8874                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8875                 return WERR_ACCESS_DENIED;
8876         }
8877
8878         if (r->in.info_ctr->level != 1) {
8879                 return WERR_INVALID_LEVEL;
8880         }
8881
8882         form = r->in.info_ctr->info.info1;
8883         if (!form) {
8884                 return WERR_INVALID_PARAM;
8885         }
8886
8887         tmp_ctx = talloc_new(p->mem_ctx);
8888         if (!tmp_ctx) {
8889                 return WERR_NOMEM;
8890         }
8891
8892         status = winreg_printer_binding_handle(tmp_ctx,
8893                                                get_session_info_system(),
8894                                                p->msg_ctx,
8895                                                &b);
8896         if (!W_ERROR_IS_OK(status)) {
8897                 goto done;
8898         }
8899
8900         status = winreg_printer_setform1(tmp_ctx, b,
8901                                          form_name,
8902                                          form);
8903         if (!W_ERROR_IS_OK(status)) {
8904                 goto done;
8905         }
8906
8907         /*
8908          * ChangeID must always be set if this is a printer
8909          */
8910         if (Printer->printer_type == SPLHND_PRINTER) {
8911                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8912                         status = WERR_BADFID;
8913                         goto done;
8914                 }
8915
8916                 status = winreg_printer_update_changeid(tmp_ctx, b,
8917                                                         lp_const_servicename(snum));
8918         }
8919
8920 done:
8921         talloc_free(tmp_ctx);
8922         return status;
8923 }
8924
8925 /****************************************************************************
8926  fill_print_processor1
8927 ****************************************************************************/
8928
8929 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8930                                     struct spoolss_PrintProcessorInfo1 *r,
8931                                     const char *print_processor_name)
8932 {
8933         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8934         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8935
8936         return WERR_OK;
8937 }
8938
8939 /****************************************************************************
8940  enumprintprocessors level 1.
8941 ****************************************************************************/
8942
8943 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8944                                           union spoolss_PrintProcessorInfo **info_p,
8945                                           uint32_t *count)
8946 {
8947         union spoolss_PrintProcessorInfo *info;
8948         WERROR result;
8949
8950         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8951         W_ERROR_HAVE_NO_MEMORY(info);
8952
8953         *count = 1;
8954
8955         result = fill_print_processor1(info, &info[0].info1, "winprint");
8956         if (!W_ERROR_IS_OK(result)) {
8957                 goto out;
8958         }
8959
8960  out:
8961         if (!W_ERROR_IS_OK(result)) {
8962                 TALLOC_FREE(info);
8963                 *count = 0;
8964                 return result;
8965         }
8966
8967         *info_p = info;
8968
8969         return WERR_OK;
8970 }
8971
8972 /****************************************************************
8973  _spoolss_EnumPrintProcessors
8974 ****************************************************************/
8975
8976 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8977                                     struct spoolss_EnumPrintProcessors *r)
8978 {
8979         WERROR result;
8980
8981         /* that's an [in out] buffer */
8982
8983         if (!r->in.buffer && (r->in.offered != 0)) {
8984                 return WERR_INVALID_PARAM;
8985         }
8986
8987         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8988
8989         /*
8990          * Enumerate the print processors ...
8991          *
8992          * Just reply with "winprint", to keep NT happy
8993          * and I can use my nice printer checker.
8994          */
8995
8996         *r->out.count = 0;
8997         *r->out.needed = 0;
8998         *r->out.info = NULL;
8999
9000         if (!get_short_archi(r->in.environment)) {
9001                 return WERR_INVALID_ENVIRONMENT;
9002         }
9003
9004         switch (r->in.level) {
9005         case 1:
9006                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9007                                                      r->out.count);
9008                 break;
9009         default:
9010                 return WERR_UNKNOWN_LEVEL;
9011         }
9012
9013         if (!W_ERROR_IS_OK(result)) {
9014                 return result;
9015         }
9016
9017         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9018                                                      spoolss_EnumPrintProcessors,
9019                                                      *r->out.info, r->in.level,
9020                                                      *r->out.count);
9021         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9022         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9023
9024         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9025 }
9026
9027 /****************************************************************************
9028  fill_printprocdatatype1
9029 ****************************************************************************/
9030
9031 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9032                                       struct spoolss_PrintProcDataTypesInfo1 *r,
9033                                       const char *name_array)
9034 {
9035         r->name_array = talloc_strdup(mem_ctx, name_array);
9036         W_ERROR_HAVE_NO_MEMORY(r->name_array);
9037
9038         return WERR_OK;
9039 }
9040
9041 /****************************************************************************
9042  enumprintprocdatatypes level 1.
9043 ****************************************************************************/
9044
9045 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9046                                              union spoolss_PrintProcDataTypesInfo **info_p,
9047                                              uint32_t *count)
9048 {
9049         WERROR result;
9050         union spoolss_PrintProcDataTypesInfo *info;
9051
9052         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9053         W_ERROR_HAVE_NO_MEMORY(info);
9054
9055         *count = 1;
9056
9057         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9058         if (!W_ERROR_IS_OK(result)) {
9059                 goto out;
9060         }
9061
9062  out:
9063         if (!W_ERROR_IS_OK(result)) {
9064                 TALLOC_FREE(info);
9065                 *count = 0;
9066                 return result;
9067         }
9068
9069         *info_p = info;
9070
9071         return WERR_OK;
9072 }
9073
9074 /****************************************************************
9075  _spoolss_EnumPrintProcDataTypes
9076 ****************************************************************/
9077
9078 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9079                                        struct spoolss_EnumPrintProcDataTypes *r)
9080 {
9081         WERROR result;
9082
9083         /* that's an [in out] buffer */
9084
9085         if (!r->in.buffer && (r->in.offered != 0)) {
9086                 return WERR_INVALID_PARAM;
9087         }
9088
9089         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9090
9091         *r->out.count = 0;
9092         *r->out.needed = 0;
9093         *r->out.info = NULL;
9094
9095         if (r->in.print_processor_name == NULL ||
9096             !strequal(r->in.print_processor_name, "winprint")) {
9097                 return WERR_UNKNOWN_PRINTPROCESSOR;
9098         }
9099
9100         switch (r->in.level) {
9101         case 1:
9102                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9103                                                         r->out.count);
9104                 break;
9105         default:
9106                 return WERR_UNKNOWN_LEVEL;
9107         }
9108
9109         if (!W_ERROR_IS_OK(result)) {
9110                 return result;
9111         }
9112
9113         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9114                                                      spoolss_EnumPrintProcDataTypes,
9115                                                      *r->out.info, r->in.level,
9116                                                      *r->out.count);
9117         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9118         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9119
9120         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9121 }
9122
9123 /****************************************************************************
9124  fill_monitor_1
9125 ****************************************************************************/
9126
9127 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9128                              struct spoolss_MonitorInfo1 *r,
9129                              const char *monitor_name)
9130 {
9131         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9132         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9133
9134         return WERR_OK;
9135 }
9136
9137 /****************************************************************************
9138  fill_monitor_2
9139 ****************************************************************************/
9140
9141 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9142                              struct spoolss_MonitorInfo2 *r,
9143                              const char *monitor_name,
9144                              const char *environment,
9145                              const char *dll_name)
9146 {
9147         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9148         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9149         r->environment                  = talloc_strdup(mem_ctx, environment);
9150         W_ERROR_HAVE_NO_MEMORY(r->environment);
9151         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9152         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9153
9154         return WERR_OK;
9155 }
9156
9157 /****************************************************************************
9158  enumprintmonitors level 1.
9159 ****************************************************************************/
9160
9161 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9162                                         union spoolss_MonitorInfo **info_p,
9163                                         uint32_t *count)
9164 {
9165         union spoolss_MonitorInfo *info;
9166         WERROR result = WERR_OK;
9167
9168         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9169         W_ERROR_HAVE_NO_MEMORY(info);
9170
9171         *count = 2;
9172
9173         result = fill_monitor_1(info, &info[0].info1,
9174                                 SPL_LOCAL_PORT);
9175         if (!W_ERROR_IS_OK(result)) {
9176                 goto out;
9177         }
9178
9179         result = fill_monitor_1(info, &info[1].info1,
9180                                 SPL_TCPIP_PORT);
9181         if (!W_ERROR_IS_OK(result)) {
9182                 goto out;
9183         }
9184
9185 out:
9186         if (!W_ERROR_IS_OK(result)) {
9187                 TALLOC_FREE(info);
9188                 *count = 0;
9189                 return result;
9190         }
9191
9192         *info_p = info;
9193
9194         return WERR_OK;
9195 }
9196
9197 /****************************************************************************
9198  enumprintmonitors level 2.
9199 ****************************************************************************/
9200
9201 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9202                                         union spoolss_MonitorInfo **info_p,
9203                                         uint32_t *count)
9204 {
9205         union spoolss_MonitorInfo *info;
9206         WERROR result = WERR_OK;
9207
9208         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9209         W_ERROR_HAVE_NO_MEMORY(info);
9210
9211         *count = 2;
9212
9213         result = fill_monitor_2(info, &info[0].info2,
9214                                 SPL_LOCAL_PORT,
9215                                 "Windows NT X86", /* FIXME */
9216                                 "localmon.dll");
9217         if (!W_ERROR_IS_OK(result)) {
9218                 goto out;
9219         }
9220
9221         result = fill_monitor_2(info, &info[1].info2,
9222                                 SPL_TCPIP_PORT,
9223                                 "Windows NT X86", /* FIXME */
9224                                 "tcpmon.dll");
9225         if (!W_ERROR_IS_OK(result)) {
9226                 goto out;
9227         }
9228
9229 out:
9230         if (!W_ERROR_IS_OK(result)) {
9231                 TALLOC_FREE(info);
9232                 *count = 0;
9233                 return result;
9234         }
9235
9236         *info_p = info;
9237
9238         return WERR_OK;
9239 }
9240
9241 /****************************************************************
9242  _spoolss_EnumMonitors
9243 ****************************************************************/
9244
9245 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9246                              struct spoolss_EnumMonitors *r)
9247 {
9248         WERROR result;
9249
9250         /* that's an [in out] buffer */
9251
9252         if (!r->in.buffer && (r->in.offered != 0)) {
9253                 return WERR_INVALID_PARAM;
9254         }
9255
9256         DEBUG(5,("_spoolss_EnumMonitors\n"));
9257
9258         /*
9259          * Enumerate the print monitors ...
9260          *
9261          * Just reply with "Local Port", to keep NT happy
9262          * and I can use my nice printer checker.
9263          */
9264
9265         *r->out.count = 0;
9266         *r->out.needed = 0;
9267         *r->out.info = NULL;
9268
9269         switch (r->in.level) {
9270         case 1:
9271                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9272                                                    r->out.count);
9273                 break;
9274         case 2:
9275                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9276                                                    r->out.count);
9277                 break;
9278         default:
9279                 return WERR_UNKNOWN_LEVEL;
9280         }
9281
9282         if (!W_ERROR_IS_OK(result)) {
9283                 return result;
9284         }
9285
9286         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9287                                                      spoolss_EnumMonitors,
9288                                                      *r->out.info, r->in.level,
9289                                                      *r->out.count);
9290         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9291         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9292
9293         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9294 }
9295
9296 /****************************************************************************
9297 ****************************************************************************/
9298
9299 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9300                              const print_queue_struct *queue,
9301                              int count, int snum,
9302                              struct spoolss_PrinterInfo2 *pinfo2,
9303                              uint32_t jobid,
9304                              struct spoolss_JobInfo1 *r)
9305 {
9306         int i = 0;
9307         bool found = false;
9308
9309         for (i=0; i<count; i++) {
9310                 if (queue[i].sysjob == (int)jobid) {
9311                         found = true;
9312                         break;
9313                 }
9314         }
9315
9316         if (found == false) {
9317                 /* NT treats not found as bad param... yet another bad choice */
9318                 return WERR_INVALID_PARAM;
9319         }
9320
9321         return fill_job_info1(mem_ctx,
9322                               r,
9323                               &queue[i],
9324                               i,
9325                               snum,
9326                               pinfo2);
9327 }
9328
9329 /****************************************************************************
9330 ****************************************************************************/
9331
9332 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9333                              const print_queue_struct *queue,
9334                              int count, int snum,
9335                              struct spoolss_PrinterInfo2 *pinfo2,
9336                              uint32_t jobid,
9337                              struct spoolss_JobInfo2 *r)
9338 {
9339         int i = 0;
9340         bool found = false;
9341         struct spoolss_DeviceMode *devmode;
9342         WERROR result;
9343
9344         for (i=0; i<count; i++) {
9345                 if (queue[i].sysjob == (int)jobid) {
9346                         found = true;
9347                         break;
9348                 }
9349         }
9350
9351         if (found == false) {
9352                 /* NT treats not found as bad param... yet another bad
9353                    choice */
9354                 return WERR_INVALID_PARAM;
9355         }
9356
9357         /*
9358          * if the print job does not have a DEVMODE associated with it,
9359          * just use the one for the printer. A NULL devicemode is not
9360          *  a failure condition
9361          */
9362
9363         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9364         if (!devmode) {
9365                 result = spoolss_create_default_devmode(mem_ctx,
9366                                                 pinfo2->printername,
9367                                                 &devmode);
9368                 if (!W_ERROR_IS_OK(result)) {
9369                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9370                         return result;
9371                 }
9372         }
9373
9374         return fill_job_info2(mem_ctx,
9375                               r,
9376                               &queue[i],
9377                               i,
9378                               snum,
9379                               pinfo2,
9380                               devmode);
9381 }
9382
9383 /****************************************************************
9384  _spoolss_GetJob
9385 ****************************************************************/
9386
9387 WERROR _spoolss_GetJob(struct pipes_struct *p,
9388                        struct spoolss_GetJob *r)
9389 {
9390         WERROR result = WERR_OK;
9391         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9392         int snum;
9393         int count;
9394         print_queue_struct      *queue = NULL;
9395         print_status_struct prt_status;
9396
9397         /* that's an [in out] buffer */
9398
9399         if (!r->in.buffer && (r->in.offered != 0)) {
9400                 return WERR_INVALID_PARAM;
9401         }
9402
9403         DEBUG(5,("_spoolss_GetJob\n"));
9404
9405         *r->out.needed = 0;
9406
9407         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9408                 return WERR_BADFID;
9409         }
9410
9411         result = winreg_get_printer_internal(p->mem_ctx,
9412                                     get_session_info_system(),
9413                                     p->msg_ctx,
9414                                     lp_const_servicename(snum),
9415                                     &pinfo2);
9416         if (!W_ERROR_IS_OK(result)) {
9417                 return result;
9418         }
9419
9420         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9421
9422         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9423                      count, prt_status.status, prt_status.message));
9424
9425         switch (r->in.level) {
9426         case 1:
9427                 result = getjob_level_1(p->mem_ctx,
9428                                         queue, count, snum, pinfo2,
9429                                         r->in.job_id, &r->out.info->info1);
9430                 break;
9431         case 2:
9432                 result = getjob_level_2(p->mem_ctx,
9433                                         queue, count, snum, pinfo2,
9434                                         r->in.job_id, &r->out.info->info2);
9435                 break;
9436         default:
9437                 result = WERR_UNKNOWN_LEVEL;
9438                 break;
9439         }
9440
9441         SAFE_FREE(queue);
9442         TALLOC_FREE(pinfo2);
9443
9444         if (!W_ERROR_IS_OK(result)) {
9445                 TALLOC_FREE(r->out.info);
9446                 return result;
9447         }
9448
9449         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9450                                                                                    r->in.level);
9451         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9452
9453         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9454 }
9455
9456 /****************************************************************
9457  _spoolss_GetPrinterDataEx
9458 ****************************************************************/
9459
9460 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9461                                  struct spoolss_GetPrinterDataEx *r)
9462 {
9463
9464         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9465         const char *printer;
9466         int                     snum = 0;
9467         WERROR result = WERR_OK;
9468         DATA_BLOB blob;
9469         enum winreg_Type val_type = REG_NONE;
9470         uint8_t *val_data = NULL;
9471         uint32_t val_size = 0;
9472         struct dcerpc_binding_handle *b;
9473         TALLOC_CTX *tmp_ctx;
9474
9475         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9476
9477         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9478                 r->in.key_name, r->in.value_name));
9479
9480         /* in case of problem, return some default values */
9481
9482         *r->out.needed  = 0;
9483         *r->out.type    = REG_NONE;
9484
9485         tmp_ctx = talloc_new(p->mem_ctx);
9486         if (!tmp_ctx) {
9487                 return WERR_NOMEM;
9488         }
9489
9490         if (!Printer) {
9491                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9492                         OUR_HANDLE(r->in.handle)));
9493                 result = WERR_BADFID;
9494                 goto done;
9495         }
9496
9497         /* check to see if the keyname is valid */
9498         if (!strlen(r->in.key_name)) {
9499                 result = WERR_INVALID_PARAM;
9500                 goto done;
9501         }
9502
9503         /* Is the handle to a printer or to the server? */
9504
9505         if (Printer->printer_type == SPLHND_SERVER) {
9506
9507                 union spoolss_PrinterData data;
9508
9509                 result = getprinterdata_printer_server(tmp_ctx,
9510                                                        r->in.value_name,
9511                                                        r->out.type,
9512                                                        &data);
9513                 if (!W_ERROR_IS_OK(result)) {
9514                         goto done;
9515                 }
9516
9517                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9518                                                   *r->out.type, &data);
9519                 if (!W_ERROR_IS_OK(result)) {
9520                         goto done;
9521                 }
9522
9523                 *r->out.needed = blob.length;
9524
9525                 if (r->in.offered >= *r->out.needed) {
9526                         memcpy(r->out.data, blob.data, blob.length);
9527                 }
9528
9529                 result = WERR_OK;
9530                 goto done;
9531         }
9532
9533         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9534                 result = WERR_BADFID;
9535                 goto done;
9536         }
9537         printer = lp_const_servicename(snum);
9538
9539         result = winreg_printer_binding_handle(tmp_ctx,
9540                                                get_session_info_system(),
9541                                                p->msg_ctx,
9542                                                &b);
9543         if (!W_ERROR_IS_OK(result)) {
9544                 goto done;
9545         }
9546
9547         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9548         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9549             strequal(r->in.value_name, "ChangeId")) {
9550                 *r->out.type = REG_DWORD;
9551                 *r->out.needed = 4;
9552                 if (r->in.offered >= *r->out.needed) {
9553                         uint32_t changeid = 0;
9554
9555                         result = winreg_printer_get_changeid(tmp_ctx, b,
9556                                                              printer,
9557                                                              &changeid);
9558                         if (!W_ERROR_IS_OK(result)) {
9559                                 goto done;
9560                         }
9561
9562                         SIVAL(r->out.data, 0, changeid);
9563                         result = WERR_OK;
9564                 }
9565                 goto done;
9566         }
9567
9568         result = winreg_get_printer_dataex(tmp_ctx, b,
9569                                            printer,
9570                                            r->in.key_name,
9571                                            r->in.value_name,
9572                                            &val_type,
9573                                            &val_data,
9574                                            &val_size);
9575         if (!W_ERROR_IS_OK(result)) {
9576                 goto done;
9577         }
9578
9579         *r->out.needed = val_size;
9580         *r->out.type = val_type;
9581
9582         if (r->in.offered >= *r->out.needed) {
9583                 memcpy(r->out.data, val_data, val_size);
9584         }
9585
9586 done:
9587         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9588
9589         if (W_ERROR_IS_OK(result)) {
9590                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9591         }
9592
9593         talloc_free(tmp_ctx);
9594         return result;
9595 }
9596
9597 /****************************************************************
9598  _spoolss_SetPrinterDataEx
9599 ****************************************************************/
9600
9601 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9602                                  struct spoolss_SetPrinterDataEx *r)
9603 {
9604         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9605         int                     snum = 0;
9606         WERROR                  result = WERR_OK;
9607         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9608         char                    *oid_string;
9609         struct dcerpc_binding_handle *b;
9610         TALLOC_CTX *tmp_ctx;
9611
9612         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9613
9614         /* From MSDN documentation of SetPrinterDataEx: pass request to
9615            SetPrinterData if key is "PrinterDriverData" */
9616
9617         if (!Printer) {
9618                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9619                         OUR_HANDLE(r->in.handle)));
9620                 return WERR_BADFID;
9621         }
9622
9623         if (Printer->printer_type == SPLHND_SERVER) {
9624                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9625                         "Not implemented for server handles yet\n"));
9626                 return WERR_INVALID_PARAM;
9627         }
9628
9629         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9630                 return WERR_BADFID;
9631         }
9632
9633         /*
9634          * Access check : NT returns "access denied" if you make a
9635          * SetPrinterData call without the necessary privildge.
9636          * we were originally returning OK if nothing changed
9637          * which made Win2k issue **a lot** of SetPrinterData
9638          * when connecting to a printer  --jerry
9639          */
9640
9641         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9642                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9643                         "change denied by handle access permissions\n"));
9644                 return WERR_ACCESS_DENIED;
9645         }
9646
9647         tmp_ctx = talloc_new(p->mem_ctx);
9648         if (!tmp_ctx) {
9649                 return WERR_NOMEM;
9650         }
9651
9652         result = winreg_printer_binding_handle(tmp_ctx,
9653                                                get_session_info_system(),
9654                                                p->msg_ctx,
9655                                                &b);
9656         if (!W_ERROR_IS_OK(result)) {
9657                 goto done;
9658         }
9659
9660         result = winreg_get_printer(tmp_ctx, b,
9661                                     lp_servicename(talloc_tos(), snum),
9662                                     &pinfo2);
9663         if (!W_ERROR_IS_OK(result)) {
9664                 goto done;
9665         }
9666
9667         /* check for OID in valuename */
9668
9669         oid_string = strchr(r->in.value_name, ',');
9670         if (oid_string) {
9671                 *oid_string = '\0';
9672                 oid_string++;
9673         }
9674
9675         /* save the registry data */
9676
9677         result = winreg_set_printer_dataex(tmp_ctx, b,
9678                                            pinfo2->sharename,
9679                                            r->in.key_name,
9680                                            r->in.value_name,
9681                                            r->in.type,
9682                                            r->in.data,
9683                                            r->in.offered);
9684
9685         if (W_ERROR_IS_OK(result)) {
9686                 /* save the OID if one was specified */
9687                 if (oid_string) {
9688                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9689                                 r->in.key_name, SPOOL_OID_KEY);
9690                         if (!str) {
9691                                 result = WERR_NOMEM;
9692                                 goto done;
9693                         }
9694
9695                         /*
9696                          * I'm not checking the status here on purpose.  Don't know
9697                          * if this is right, but I'm returning the status from the
9698                          * previous set_printer_dataex() call.  I have no idea if
9699                          * this is right.    --jerry
9700                          */
9701                         winreg_set_printer_dataex(tmp_ctx, b,
9702                                                   pinfo2->sharename,
9703                                                   str,
9704                                                   r->in.value_name,
9705                                                   REG_SZ,
9706                                                   (uint8_t *) oid_string,
9707                                                   strlen(oid_string) + 1);
9708                 }
9709
9710                 result = winreg_printer_update_changeid(tmp_ctx, b,
9711                                                         lp_const_servicename(snum));
9712
9713         }
9714
9715 done:
9716         talloc_free(tmp_ctx);
9717         return result;
9718 }
9719
9720 /****************************************************************
9721  _spoolss_DeletePrinterDataEx
9722 ****************************************************************/
9723
9724 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9725                                     struct spoolss_DeletePrinterDataEx *r)
9726 {
9727         const char *printer;
9728         int             snum=0;
9729         WERROR          status = WERR_OK;
9730         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9731
9732         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9733
9734         if (!Printer) {
9735                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9736                         "Invalid handle (%s:%u:%u).\n",
9737                         OUR_HANDLE(r->in.handle)));
9738                 return WERR_BADFID;
9739         }
9740
9741         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9742                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9743                         "printer properties change denied by handle\n"));
9744                 return WERR_ACCESS_DENIED;
9745         }
9746
9747         if (!r->in.value_name || !r->in.key_name) {
9748                 return WERR_NOMEM;
9749         }
9750
9751         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9752                 return WERR_BADFID;
9753         }
9754         printer = lp_const_servicename(snum);
9755
9756         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9757                                               get_session_info_system(),
9758                                               p->msg_ctx,
9759                                               printer,
9760                                               r->in.key_name,
9761                                               r->in.value_name);
9762         if (W_ERROR_IS_OK(status)) {
9763                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9764                                                         get_session_info_system(),
9765                                                         p->msg_ctx,
9766                                                         printer);
9767         }
9768
9769         return status;
9770 }
9771
9772 /****************************************************************
9773  _spoolss_EnumPrinterKey
9774 ****************************************************************/
9775
9776 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9777                                struct spoolss_EnumPrinterKey *r)
9778 {
9779         uint32_t        num_keys;
9780         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9781         int             snum = 0;
9782         WERROR          result = WERR_BADFILE;
9783         const char **array = NULL;
9784         DATA_BLOB blob;
9785
9786         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9787
9788         if (!Printer) {
9789                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9790                         OUR_HANDLE(r->in.handle)));
9791                 return WERR_BADFID;
9792         }
9793
9794         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9795                 return WERR_BADFID;
9796         }
9797
9798         result = winreg_enum_printer_key_internal(p->mem_ctx,
9799                                          get_session_info_system(),
9800                                          p->msg_ctx,
9801                                          lp_const_servicename(snum),
9802                                          r->in.key_name,
9803                                          &num_keys,
9804                                          &array);
9805         if (!W_ERROR_IS_OK(result)) {
9806                 goto done;
9807         }
9808
9809         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9810                 result = WERR_NOMEM;
9811                 goto done;
9812         }
9813
9814         *r->out._ndr_size = r->in.offered / 2;
9815         *r->out.needed = blob.length;
9816
9817         if (r->in.offered < *r->out.needed) {
9818                 result = WERR_MORE_DATA;
9819         } else {
9820                 result = WERR_OK;
9821                 r->out.key_buffer->string_array = array;
9822         }
9823
9824  done:
9825         if (!W_ERROR_IS_OK(result)) {
9826                 TALLOC_FREE(array);
9827                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9828                         *r->out.needed = 0;
9829                 }
9830         }
9831
9832         return result;
9833 }
9834
9835 /****************************************************************
9836  _spoolss_DeletePrinterKey
9837 ****************************************************************/
9838
9839 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9840                                  struct spoolss_DeletePrinterKey *r)
9841 {
9842         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9843         int                     snum=0;
9844         WERROR                  status;
9845         const char *printer;
9846         struct dcerpc_binding_handle *b;
9847         TALLOC_CTX *tmp_ctx;
9848
9849         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9850
9851         if (!Printer) {
9852                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9853                         OUR_HANDLE(r->in.handle)));
9854                 return WERR_BADFID;
9855         }
9856
9857         /* if keyname == NULL, return error */
9858         if ( !r->in.key_name )
9859                 return WERR_INVALID_PARAM;
9860
9861         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9862                 return WERR_BADFID;
9863         }
9864
9865         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9866                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9867                         "printer properties change denied by handle\n"));
9868                 return WERR_ACCESS_DENIED;
9869         }
9870
9871         printer = lp_const_servicename(snum);
9872
9873         tmp_ctx = talloc_new(p->mem_ctx);
9874         if (!tmp_ctx) {
9875                 return WERR_NOMEM;
9876         }
9877
9878         status = winreg_printer_binding_handle(tmp_ctx,
9879                                                get_session_info_system(),
9880                                                p->msg_ctx,
9881                                                &b);
9882         if (!W_ERROR_IS_OK(status)) {
9883                 goto done;
9884         }
9885
9886         /* delete the key and all subkeys */
9887         status = winreg_delete_printer_key(tmp_ctx, b,
9888                                            printer,
9889                                            r->in.key_name);
9890         if (W_ERROR_IS_OK(status)) {
9891                 status = winreg_printer_update_changeid(tmp_ctx, b,
9892                                                         printer);
9893         }
9894
9895 done:
9896         talloc_free(tmp_ctx);
9897         return status;
9898 }
9899
9900 /****************************************************************
9901  _spoolss_EnumPrinterDataEx
9902 ****************************************************************/
9903
9904 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9905                                   struct spoolss_EnumPrinterDataEx *r)
9906 {
9907         uint32_t        count = 0;
9908         struct spoolss_PrinterEnumValues *info = NULL;
9909         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9910         int             snum;
9911         WERROR          result;
9912
9913         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9914
9915         *r->out.count = 0;
9916         *r->out.needed = 0;
9917         *r->out.info = NULL;
9918
9919         if (!Printer) {
9920                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9921                         OUR_HANDLE(r->in.handle)));
9922                 return WERR_BADFID;
9923         }
9924
9925         /*
9926          * first check for a keyname of NULL or "".  Win2k seems to send
9927          * this a lot and we should send back WERR_INVALID_PARAM
9928          * no need to spend time looking up the printer in this case.
9929          * --jerry
9930          */
9931
9932         if (!strlen(r->in.key_name)) {
9933                 result = WERR_INVALID_PARAM;
9934                 goto done;
9935         }
9936
9937         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9938                 return WERR_BADFID;
9939         }
9940
9941         /* now look for a match on the key name */
9942         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9943                                             get_session_info_system(),
9944                                             p->msg_ctx,
9945                                             lp_const_servicename(snum),
9946                                             r->in.key_name,
9947                                             &count,
9948                                             &info);
9949         if (!W_ERROR_IS_OK(result)) {
9950                 goto done;
9951         }
9952
9953 #if 0 /* FIXME - gd */
9954         /* housekeeping information in the reply */
9955
9956         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9957          * the hand marshalled container size is a multiple
9958          * of 4 bytes for RPC alignment.
9959          */
9960
9961         if (needed % 4) {
9962                 needed += 4-(needed % 4);
9963         }
9964 #endif
9965         *r->out.count   = count;
9966         *r->out.info    = info;
9967
9968  done:
9969         if (!W_ERROR_IS_OK(result)) {
9970                 return result;
9971         }
9972
9973         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9974                                                spoolss_EnumPrinterDataEx,
9975                                                *r->out.info,
9976                                                *r->out.count);
9977         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9978         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9979
9980         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9981 }
9982
9983 /****************************************************************************
9984 ****************************************************************************/
9985
9986 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9987                                                  const char *servername,
9988                                                  const char *environment,
9989                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9990 {
9991         WERROR werr;
9992         char *path = NULL;
9993
9994         werr = compose_spoolss_server_path(mem_ctx,
9995                                            servername,
9996                                            environment,
9997                                            SPOOLSS_PRTPROCS_PATH,
9998                                            &path);
9999         if (!W_ERROR_IS_OK(werr)) {
10000                 return werr;
10001         }
10002
10003         DEBUG(4,("print processor directory: [%s]\n", path));
10004
10005         r->directory_name = path;
10006
10007         return WERR_OK;
10008 }
10009
10010 /****************************************************************
10011  _spoolss_GetPrintProcessorDirectory
10012 ****************************************************************/
10013
10014 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10015                                            struct spoolss_GetPrintProcessorDirectory *r)
10016 {
10017         WERROR result;
10018         char *prnproc_share = NULL;
10019         bool prnproc_share_exists = false;
10020         int snum;
10021
10022         /* that's an [in out] buffer */
10023
10024         if (!r->in.buffer && (r->in.offered != 0)) {
10025                 return WERR_INVALID_PARAM;
10026         }
10027
10028         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10029                 r->in.level));
10030
10031         *r->out.needed = 0;
10032
10033         /* r->in.level is ignored */
10034
10035         /* We always should reply with a local print processor directory so that
10036          * users are not forced to have a [prnproc$] share on the Samba spoolss
10037          * server, if users decide to do so, lets announce it though - Guenther */
10038
10039         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10040         if (!prnproc_share) {
10041                 return WERR_NOMEM;
10042         }
10043         if (snum != -1) {
10044                 prnproc_share_exists = true;
10045         }
10046
10047         result = getprintprocessordirectory_level_1(p->mem_ctx,
10048                                                     prnproc_share_exists ? r->in.server : NULL,
10049                                                     r->in.environment,
10050                                                     &r->out.info->info1);
10051         if (!W_ERROR_IS_OK(result)) {
10052                 TALLOC_FREE(r->out.info);
10053                 return result;
10054         }
10055
10056         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10057                                                                                    r->out.info, r->in.level);
10058         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10059
10060         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10061 }
10062
10063 /*******************************************************************
10064  ********************************************************************/
10065
10066 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10067                                const char *dllname)
10068 {
10069         enum ndr_err_code ndr_err;
10070         struct spoolss_MonitorUi ui;
10071
10072         ui.dll_name = dllname;
10073
10074         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10075                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10076         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10077                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10078         }
10079         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10080 }
10081
10082 /*******************************************************************
10083  Streams the monitor UI DLL name in UNICODE
10084 *******************************************************************/
10085
10086 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10087                                struct security_token *token, DATA_BLOB *in,
10088                                DATA_BLOB *out, uint32_t *needed)
10089 {
10090         const char *dllname = "tcpmonui.dll";
10091
10092         *needed = (strlen(dllname)+1) * 2;
10093
10094         if (out->length < *needed) {
10095                 return WERR_INSUFFICIENT_BUFFER;
10096         }
10097
10098         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10099                 return WERR_NOMEM;
10100         }
10101
10102         return WERR_OK;
10103 }
10104
10105 /*******************************************************************
10106  ********************************************************************/
10107
10108 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10109                              struct spoolss_PortData1 *port1,
10110                              const DATA_BLOB *buf)
10111 {
10112         enum ndr_err_code ndr_err;
10113         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10114                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10115         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10116                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10117         }
10118         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10119 }
10120
10121 /*******************************************************************
10122  ********************************************************************/
10123
10124 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10125                              struct spoolss_PortData2 *port2,
10126                              const DATA_BLOB *buf)
10127 {
10128         enum ndr_err_code ndr_err;
10129         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10130                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10131         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10132                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10133         }
10134         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10135 }
10136
10137 /*******************************************************************
10138  Create a new TCP/IP port
10139 *******************************************************************/
10140
10141 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10142                              struct security_token *token, DATA_BLOB *in,
10143                              DATA_BLOB *out, uint32_t *needed)
10144 {
10145         struct spoolss_PortData1 port1;
10146         struct spoolss_PortData2 port2;
10147         char *device_uri = NULL;
10148         uint32_t version;
10149
10150         const char *portname;
10151         const char *hostaddress;
10152         const char *queue;
10153         uint32_t port_number;
10154         uint32_t protocol;
10155
10156         /* peek for spoolss_PortData version */
10157
10158         if (!in || (in->length < (128 + 4))) {
10159                 return WERR_GENERAL_FAILURE;
10160         }
10161
10162         version = IVAL(in->data, 128);
10163
10164         switch (version) {
10165                 case 1:
10166                         ZERO_STRUCT(port1);
10167
10168                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10169                                 return WERR_NOMEM;
10170                         }
10171
10172                         portname        = port1.portname;
10173                         hostaddress     = port1.hostaddress;
10174                         queue           = port1.queue;
10175                         protocol        = port1.protocol;
10176                         port_number     = port1.port_number;
10177
10178                         break;
10179                 case 2:
10180                         ZERO_STRUCT(port2);
10181
10182                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10183                                 return WERR_NOMEM;
10184                         }
10185
10186                         portname        = port2.portname;
10187                         hostaddress     = port2.hostaddress;
10188                         queue           = port2.queue;
10189                         protocol        = port2.protocol;
10190                         port_number     = port2.port_number;
10191
10192                         break;
10193                 default:
10194                         DEBUG(1,("xcvtcp_addport: "
10195                                 "unknown version of port_data: %d\n", version));
10196                         return WERR_UNKNOWN_PORT;
10197         }
10198
10199         /* create the device URI and call the add_port_hook() */
10200
10201         switch (protocol) {
10202         case PROTOCOL_RAWTCP_TYPE:
10203                 device_uri = talloc_asprintf(mem_ctx,
10204                                 "socket://%s:%d/", hostaddress,
10205                                 port_number);
10206                 break;
10207
10208         case PROTOCOL_LPR_TYPE:
10209                 device_uri = talloc_asprintf(mem_ctx,
10210                         "lpr://%s/%s", hostaddress, queue );
10211                 break;
10212
10213         default:
10214                 return WERR_UNKNOWN_PORT;
10215         }
10216
10217         if (!device_uri) {
10218                 return WERR_NOMEM;
10219         }
10220
10221         return add_port_hook(mem_ctx, token, portname, device_uri);
10222 }
10223
10224 /*******************************************************************
10225 *******************************************************************/
10226
10227 struct xcv_api_table xcvtcp_cmds[] = {
10228         { "MonitorUI",  xcvtcp_monitorui },
10229         { "AddPort",    xcvtcp_addport},
10230         { NULL,         NULL }
10231 };
10232
10233 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10234                                      struct security_token *token, const char *command,
10235                                      DATA_BLOB *inbuf,
10236                                      DATA_BLOB *outbuf,
10237                                      uint32_t *needed )
10238 {
10239         int i;
10240
10241         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10242
10243         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10244                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10245                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10246         }
10247
10248         return WERR_BADFUNC;
10249 }
10250
10251 /*******************************************************************
10252 *******************************************************************/
10253 #if 0   /* don't support management using the "Local Port" monitor */
10254
10255 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10256                                  struct security_token *token, DATA_BLOB *in,
10257                                  DATA_BLOB *out, uint32_t *needed)
10258 {
10259         const char *dllname = "localui.dll";
10260
10261         *needed = (strlen(dllname)+1) * 2;
10262
10263         if (out->length < *needed) {
10264                 return WERR_INSUFFICIENT_BUFFER;
10265         }
10266
10267         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10268                 return WERR_NOMEM;
10269         }
10270
10271         return WERR_OK;
10272 }
10273
10274 /*******************************************************************
10275 *******************************************************************/
10276
10277 struct xcv_api_table xcvlocal_cmds[] = {
10278         { "MonitorUI",  xcvlocal_monitorui },
10279         { NULL,         NULL }
10280 };
10281 #else
10282 struct xcv_api_table xcvlocal_cmds[] = {
10283         { NULL,         NULL }
10284 };
10285 #endif
10286
10287
10288
10289 /*******************************************************************
10290 *******************************************************************/
10291
10292 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10293                                        struct security_token *token, const char *command,
10294                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10295                                        uint32_t *needed)
10296 {
10297         int i;
10298
10299         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10300
10301         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10302                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10303                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10304         }
10305         return WERR_BADFUNC;
10306 }
10307
10308 /****************************************************************
10309  _spoolss_XcvData
10310 ****************************************************************/
10311
10312 WERROR _spoolss_XcvData(struct pipes_struct *p,
10313                         struct spoolss_XcvData *r)
10314 {
10315         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10316         DATA_BLOB out_data = data_blob_null;
10317         WERROR werror;
10318
10319         if (!Printer) {
10320                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10321                         OUR_HANDLE(r->in.handle)));
10322                 return WERR_BADFID;
10323         }
10324
10325         /* Has to be a handle to the TCP/IP port monitor */
10326
10327         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10328                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10329                 return WERR_BADFID;
10330         }
10331
10332         /* requires administrative access to the server */
10333
10334         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10335                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10336                 return WERR_ACCESS_DENIED;
10337         }
10338
10339         /* Allocate the outgoing buffer */
10340
10341         if (r->in.out_data_size) {
10342                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10343                 if (out_data.data == NULL) {
10344                         return WERR_NOMEM;
10345                 }
10346         }
10347
10348         switch ( Printer->printer_type ) {
10349         case SPLHND_PORTMON_TCP:
10350                 werror = process_xcvtcp_command(p->mem_ctx,
10351                                                 p->session_info->security_token,
10352                                                 r->in.function_name,
10353                                                 &r->in.in_data, &out_data,
10354                                                 r->out.needed);
10355                 break;
10356         case SPLHND_PORTMON_LOCAL:
10357                 werror = process_xcvlocal_command(p->mem_ctx,
10358                                                   p->session_info->security_token,
10359                                                   r->in.function_name,
10360                                                   &r->in.in_data, &out_data,
10361                                                   r->out.needed);
10362                 break;
10363         default:
10364                 werror = WERR_INVALID_PRINT_MONITOR;
10365         }
10366
10367         if (!W_ERROR_IS_OK(werror)) {
10368                 return werror;
10369         }
10370
10371         *r->out.status_code = 0;
10372
10373         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10374                 memcpy(r->out.out_data, out_data.data,
10375                         MIN(r->in.out_data_size, out_data.length));
10376         }
10377
10378         return WERR_OK;
10379 }
10380
10381 /****************************************************************
10382  _spoolss_AddPrintProcessor
10383 ****************************************************************/
10384
10385 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10386                                   struct spoolss_AddPrintProcessor *r)
10387 {
10388         /* for now, just indicate success and ignore the add.  We'll
10389            automatically set the winprint processor for printer
10390            entries later.  Used to debug the LexMark Optra S 1855 PCL
10391            driver --jerry */
10392
10393         return WERR_OK;
10394 }
10395
10396 /****************************************************************
10397  _spoolss_AddPort
10398 ****************************************************************/
10399
10400 WERROR _spoolss_AddPort(struct pipes_struct *p,
10401                         struct spoolss_AddPort *r)
10402 {
10403         /* do what w2k3 does */
10404
10405         return WERR_NOT_SUPPORTED;
10406 }
10407
10408 /****************************************************************
10409  _spoolss_GetPrinterDriver
10410 ****************************************************************/
10411
10412 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10413                                  struct spoolss_GetPrinterDriver *r)
10414 {
10415         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10416         return WERR_NOT_SUPPORTED;
10417 }
10418
10419 /****************************************************************
10420  _spoolss_ReadPrinter
10421 ****************************************************************/
10422
10423 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10424                             struct spoolss_ReadPrinter *r)
10425 {
10426         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10427         return WERR_NOT_SUPPORTED;
10428 }
10429
10430 /****************************************************************
10431  _spoolss_WaitForPrinterChange
10432 ****************************************************************/
10433
10434 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10435                                      struct spoolss_WaitForPrinterChange *r)
10436 {
10437         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10438         return WERR_NOT_SUPPORTED;
10439 }
10440
10441 /****************************************************************
10442  _spoolss_ConfigurePort
10443 ****************************************************************/
10444
10445 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10446                               struct spoolss_ConfigurePort *r)
10447 {
10448         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10449         return WERR_NOT_SUPPORTED;
10450 }
10451
10452 /****************************************************************
10453  _spoolss_DeletePort
10454 ****************************************************************/
10455
10456 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10457                            struct spoolss_DeletePort *r)
10458 {
10459         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10460         return WERR_NOT_SUPPORTED;
10461 }
10462
10463 /****************************************************************
10464  _spoolss_CreatePrinterIC
10465 ****************************************************************/
10466
10467 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10468                                 struct spoolss_CreatePrinterIC *r)
10469 {
10470         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10471         return WERR_NOT_SUPPORTED;
10472 }
10473
10474 /****************************************************************
10475  _spoolss_PlayGDIScriptOnPrinterIC
10476 ****************************************************************/
10477
10478 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10479                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10480 {
10481         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10482         return WERR_NOT_SUPPORTED;
10483 }
10484
10485 /****************************************************************
10486  _spoolss_DeletePrinterIC
10487 ****************************************************************/
10488
10489 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10490                                 struct spoolss_DeletePrinterIC *r)
10491 {
10492         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10493         return WERR_NOT_SUPPORTED;
10494 }
10495
10496 /****************************************************************
10497  _spoolss_AddPrinterConnection
10498 ****************************************************************/
10499
10500 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10501                                      struct spoolss_AddPrinterConnection *r)
10502 {
10503         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10504         return WERR_NOT_SUPPORTED;
10505 }
10506
10507 /****************************************************************
10508  _spoolss_DeletePrinterConnection
10509 ****************************************************************/
10510
10511 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10512                                         struct spoolss_DeletePrinterConnection *r)
10513 {
10514         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10515         return WERR_NOT_SUPPORTED;
10516 }
10517
10518 /****************************************************************
10519  _spoolss_PrinterMessageBox
10520 ****************************************************************/
10521
10522 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10523                                   struct spoolss_PrinterMessageBox *r)
10524 {
10525         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10526         return WERR_NOT_SUPPORTED;
10527 }
10528
10529 /****************************************************************
10530  _spoolss_AddMonitor
10531 ****************************************************************/
10532
10533 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10534                            struct spoolss_AddMonitor *r)
10535 {
10536         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10537         return WERR_NOT_SUPPORTED;
10538 }
10539
10540 /****************************************************************
10541  _spoolss_DeleteMonitor
10542 ****************************************************************/
10543
10544 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10545                               struct spoolss_DeleteMonitor *r)
10546 {
10547         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10548         return WERR_NOT_SUPPORTED;
10549 }
10550
10551 /****************************************************************
10552  _spoolss_DeletePrintProcessor
10553 ****************************************************************/
10554
10555 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10556                                      struct spoolss_DeletePrintProcessor *r)
10557 {
10558         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10559         return WERR_NOT_SUPPORTED;
10560 }
10561
10562 /****************************************************************
10563  _spoolss_AddPrintProvidor
10564 ****************************************************************/
10565
10566 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10567                                  struct spoolss_AddPrintProvidor *r)
10568 {
10569         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10570         return WERR_NOT_SUPPORTED;
10571 }
10572
10573 /****************************************************************
10574  _spoolss_DeletePrintProvidor
10575 ****************************************************************/
10576
10577 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10578                                     struct spoolss_DeletePrintProvidor *r)
10579 {
10580         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10581         return WERR_NOT_SUPPORTED;
10582 }
10583
10584 /****************************************************************
10585  _spoolss_FindFirstPrinterChangeNotification
10586 ****************************************************************/
10587
10588 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10589                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10590 {
10591         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10592         return WERR_NOT_SUPPORTED;
10593 }
10594
10595 /****************************************************************
10596  _spoolss_FindNextPrinterChangeNotification
10597 ****************************************************************/
10598
10599 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10600                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10601 {
10602         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10603         return WERR_NOT_SUPPORTED;
10604 }
10605
10606 /****************************************************************
10607  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10608 ****************************************************************/
10609
10610 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10611                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10612 {
10613         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10614         return WERR_NOT_SUPPORTED;
10615 }
10616
10617 /****************************************************************
10618  _spoolss_ReplyOpenPrinter
10619 ****************************************************************/
10620
10621 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10622                                  struct spoolss_ReplyOpenPrinter *r)
10623 {
10624         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10625         return WERR_NOT_SUPPORTED;
10626 }
10627
10628 /****************************************************************
10629  _spoolss_RouterReplyPrinter
10630 ****************************************************************/
10631
10632 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10633                                    struct spoolss_RouterReplyPrinter *r)
10634 {
10635         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10636         return WERR_NOT_SUPPORTED;
10637 }
10638
10639 /****************************************************************
10640  _spoolss_ReplyClosePrinter
10641 ****************************************************************/
10642
10643 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10644                                   struct spoolss_ReplyClosePrinter *r)
10645 {
10646         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10647         return WERR_NOT_SUPPORTED;
10648 }
10649
10650 /****************************************************************
10651  _spoolss_AddPortEx
10652 ****************************************************************/
10653
10654 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10655                           struct spoolss_AddPortEx *r)
10656 {
10657         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10658         return WERR_NOT_SUPPORTED;
10659 }
10660
10661 /****************************************************************
10662  _spoolss_RouterFindFirstPrinterChangeNotification
10663 ****************************************************************/
10664
10665 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10666                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10667 {
10668         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10669         return WERR_NOT_SUPPORTED;
10670 }
10671
10672 /****************************************************************
10673  _spoolss_SpoolerInit
10674 ****************************************************************/
10675
10676 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10677                             struct spoolss_SpoolerInit *r)
10678 {
10679         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10680         return WERR_NOT_SUPPORTED;
10681 }
10682
10683 /****************************************************************
10684  _spoolss_ResetPrinterEx
10685 ****************************************************************/
10686
10687 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10688                                struct spoolss_ResetPrinterEx *r)
10689 {
10690         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10691         return WERR_NOT_SUPPORTED;
10692 }
10693
10694 /****************************************************************
10695  _spoolss_RouterReplyPrinterEx
10696 ****************************************************************/
10697
10698 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10699                                      struct spoolss_RouterReplyPrinterEx *r)
10700 {
10701         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10702         return WERR_NOT_SUPPORTED;
10703 }
10704
10705 /****************************************************************
10706  _spoolss_44
10707 ****************************************************************/
10708
10709 WERROR _spoolss_44(struct pipes_struct *p,
10710                    struct spoolss_44 *r)
10711 {
10712         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10713         return WERR_NOT_SUPPORTED;
10714 }
10715
10716 /****************************************************************
10717  _spoolss_SetPort
10718 ****************************************************************/
10719
10720 WERROR _spoolss_SetPort(struct pipes_struct *p,
10721                         struct spoolss_SetPort *r)
10722 {
10723         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10724         return WERR_NOT_SUPPORTED;
10725 }
10726
10727 /****************************************************************
10728  _spoolss_4a
10729 ****************************************************************/
10730
10731 WERROR _spoolss_4a(struct pipes_struct *p,
10732                    struct spoolss_4a *r)
10733 {
10734         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10735         return WERR_NOT_SUPPORTED;
10736 }
10737
10738 /****************************************************************
10739  _spoolss_4b
10740 ****************************************************************/
10741
10742 WERROR _spoolss_4b(struct pipes_struct *p,
10743                    struct spoolss_4b *r)
10744 {
10745         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10746         return WERR_NOT_SUPPORTED;
10747 }
10748
10749 /****************************************************************
10750  _spoolss_4c
10751 ****************************************************************/
10752
10753 WERROR _spoolss_4c(struct pipes_struct *p,
10754                    struct spoolss_4c *r)
10755 {
10756         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10757         return WERR_NOT_SUPPORTED;
10758 }
10759
10760 /****************************************************************
10761  _spoolss_53
10762 ****************************************************************/
10763
10764 WERROR _spoolss_53(struct pipes_struct *p,
10765                    struct spoolss_53 *r)
10766 {
10767         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10768         return WERR_NOT_SUPPORTED;
10769 }
10770
10771 /****************************************************************
10772  _spoolss_AddPerMachineConnection
10773 ****************************************************************/
10774
10775 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10776                                         struct spoolss_AddPerMachineConnection *r)
10777 {
10778         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10779         return WERR_NOT_SUPPORTED;
10780 }
10781
10782 /****************************************************************
10783  _spoolss_DeletePerMachineConnection
10784 ****************************************************************/
10785
10786 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10787                                            struct spoolss_DeletePerMachineConnection *r)
10788 {
10789         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10790         return WERR_NOT_SUPPORTED;
10791 }
10792
10793 /****************************************************************
10794  _spoolss_EnumPerMachineConnections
10795 ****************************************************************/
10796
10797 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10798                                           struct spoolss_EnumPerMachineConnections *r)
10799 {
10800         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10801         return WERR_NOT_SUPPORTED;
10802 }
10803
10804 /****************************************************************
10805  _spoolss_5a
10806 ****************************************************************/
10807
10808 WERROR _spoolss_5a(struct pipes_struct *p,
10809                    struct spoolss_5a *r)
10810 {
10811         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10812         return WERR_NOT_SUPPORTED;
10813 }
10814
10815 /****************************************************************
10816  _spoolss_5b
10817 ****************************************************************/
10818
10819 WERROR _spoolss_5b(struct pipes_struct *p,
10820                    struct spoolss_5b *r)
10821 {
10822         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10823         return WERR_NOT_SUPPORTED;
10824 }
10825
10826 /****************************************************************
10827  _spoolss_5c
10828 ****************************************************************/
10829
10830 WERROR _spoolss_5c(struct pipes_struct *p,
10831                    struct spoolss_5c *r)
10832 {
10833         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10834         return WERR_NOT_SUPPORTED;
10835 }
10836
10837 /****************************************************************
10838  _spoolss_5d
10839 ****************************************************************/
10840
10841 WERROR _spoolss_5d(struct pipes_struct *p,
10842                    struct spoolss_5d *r)
10843 {
10844         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10845         return WERR_NOT_SUPPORTED;
10846 }
10847
10848 /****************************************************************
10849  _spoolss_5e
10850 ****************************************************************/
10851
10852 WERROR _spoolss_5e(struct pipes_struct *p,
10853                    struct spoolss_5e *r)
10854 {
10855         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10856         return WERR_NOT_SUPPORTED;
10857 }
10858
10859 /****************************************************************
10860  _spoolss_5f
10861 ****************************************************************/
10862
10863 WERROR _spoolss_5f(struct pipes_struct *p,
10864                    struct spoolss_5f *r)
10865 {
10866         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10867         return WERR_NOT_SUPPORTED;
10868 }
10869
10870 /****************************************************************
10871  _spoolss_60
10872 ****************************************************************/
10873
10874 WERROR _spoolss_60(struct pipes_struct *p,
10875                    struct spoolss_60 *r)
10876 {
10877         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10878         return WERR_NOT_SUPPORTED;
10879 }
10880
10881 /****************************************************************
10882  _spoolss_RpcSendRecvBidiData
10883 ****************************************************************/
10884
10885 WERROR _spoolss_RpcSendRecvBidiData(struct pipes_struct *p,
10886                                     struct spoolss_RpcSendRecvBidiData *r)
10887 {
10888         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10889         return WERR_NOT_SUPPORTED;
10890 }
10891
10892 /****************************************************************
10893  _spoolss_62
10894 ****************************************************************/
10895
10896 WERROR _spoolss_62(struct pipes_struct *p,
10897                    struct spoolss_62 *r)
10898 {
10899         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10900         return WERR_NOT_SUPPORTED;
10901 }
10902
10903 /****************************************************************
10904  _spoolss_63
10905 ****************************************************************/
10906
10907 WERROR _spoolss_63(struct pipes_struct *p,
10908                    struct spoolss_63 *r)
10909 {
10910         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10911         return WERR_NOT_SUPPORTED;
10912 }
10913
10914 /****************************************************************
10915  _spoolss_64
10916 ****************************************************************/
10917
10918 WERROR _spoolss_64(struct pipes_struct *p,
10919                    struct spoolss_64 *r)
10920 {
10921         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10922         return WERR_NOT_SUPPORTED;
10923 }
10924
10925 /****************************************************************
10926  _spoolss_65
10927 ****************************************************************/
10928
10929 WERROR _spoolss_65(struct pipes_struct *p,
10930                    struct spoolss_65 *r)
10931 {
10932         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10933         return WERR_NOT_SUPPORTED;
10934 }
10935
10936 /****************************************************************
10937  _spoolss_GetCorePrinterDrivers
10938 ****************************************************************/
10939
10940 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10941                                       struct spoolss_GetCorePrinterDrivers *r)
10942 {
10943         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10944         return WERR_NOT_SUPPORTED;
10945 }
10946
10947 /****************************************************************
10948  _spoolss_67
10949 ****************************************************************/
10950
10951 WERROR _spoolss_67(struct pipes_struct *p,
10952                    struct spoolss_67 *r)
10953 {
10954         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10955         return WERR_NOT_SUPPORTED;
10956 }
10957
10958 /****************************************************************
10959  _spoolss_GetPrinterDriverPackagePath
10960 ****************************************************************/
10961
10962 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10963                                             struct spoolss_GetPrinterDriverPackagePath *r)
10964 {
10965         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10966         return WERR_NOT_SUPPORTED;
10967 }
10968
10969 /****************************************************************
10970  _spoolss_69
10971 ****************************************************************/
10972
10973 WERROR _spoolss_69(struct pipes_struct *p,
10974                    struct spoolss_69 *r)
10975 {
10976         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10977         return WERR_NOT_SUPPORTED;
10978 }
10979
10980 /****************************************************************
10981  _spoolss_6a
10982 ****************************************************************/
10983
10984 WERROR _spoolss_6a(struct pipes_struct *p,
10985                    struct spoolss_6a *r)
10986 {
10987         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10988         return WERR_NOT_SUPPORTED;
10989 }
10990
10991 /****************************************************************
10992  _spoolss_6b
10993 ****************************************************************/
10994
10995 WERROR _spoolss_6b(struct pipes_struct *p,
10996                    struct spoolss_6b *r)
10997 {
10998         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10999         return WERR_NOT_SUPPORTED;
11000 }
11001
11002 /****************************************************************
11003  _spoolss_6c
11004 ****************************************************************/
11005
11006 WERROR _spoolss_6c(struct pipes_struct *p,
11007                    struct spoolss_6c *r)
11008 {
11009         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11010         return WERR_NOT_SUPPORTED;
11011 }
11012
11013 /****************************************************************
11014  _spoolss_6d
11015 ****************************************************************/
11016
11017 WERROR _spoolss_6d(struct pipes_struct *p,
11018                    struct spoolss_6d *r)
11019 {
11020         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11021         return WERR_NOT_SUPPORTED;
11022 }
11023
11024 /****************************************************************
11025  _spoolss_RpcGetJobNamedPropertyValue
11026 ****************************************************************/
11027
11028 WERROR _spoolss_RpcGetJobNamedPropertyValue(struct pipes_struct *p,
11029                                             struct spoolss_RpcGetJobNamedPropertyValue *r)
11030 {
11031         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11032         return WERR_NOT_SUPPORTED;
11033 }
11034
11035 /****************************************************************
11036  _spoolss_RpcSetJobNamedProperty
11037 ****************************************************************/
11038
11039 WERROR _spoolss_RpcSetJobNamedProperty(struct pipes_struct *p,
11040                                        struct spoolss_RpcSetJobNamedProperty *r)
11041 {
11042         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11043         return WERR_NOT_SUPPORTED;
11044 }
11045
11046 /****************************************************************
11047  _spoolss_RpcDeleteJobNamedProperty
11048 ****************************************************************/
11049
11050 WERROR _spoolss_RpcDeleteJobNamedProperty(struct pipes_struct *p,
11051                                           struct spoolss_RpcDeleteJobNamedProperty *r)
11052 {
11053         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11054         return WERR_NOT_SUPPORTED;
11055 }
11056
11057 /****************************************************************
11058  _spoolss_RpcEnumJobNamedProperties
11059 ****************************************************************/
11060
11061 WERROR _spoolss_RpcEnumJobNamedProperties(struct pipes_struct *p,
11062                                           struct spoolss_RpcEnumJobNamedProperties *r)
11063 {
11064         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11065         return WERR_NOT_SUPPORTED;
11066 }