s3:registry: remove usage of reg_objects from srv_spoolss_nt.c
[jlayton/samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "include/printing.h"
42 #include "secrets.h"
43 #include "../librpc/gen_ndr/netlogon.h"
44 #include "rpc_misc.h"
45 #include "printing/notify.h"
46 #include "serverid.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "smbd/globals.h"
50 #include "auth.h"
51 #include "messages.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
53 #include "util_tdb.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
58
59 /* macros stolen from s4 spoolss server */
60 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
61         ((info)?ndr_size_##fn(info, level, 0):0)
62
63 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
64         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
65
66 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
67         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
68
69 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
70
71 #undef DBGC_CLASS
72 #define DBGC_CLASS DBGC_RPC_SRV
73
74 #ifndef MAX_OPEN_PRINTER_EXS
75 #define MAX_OPEN_PRINTER_EXS 50
76 #endif
77
78 struct notify_back_channel;
79
80 /* structure to store the printer handles */
81 /* and a reference to what it's pointing to */
82 /* and the notify info asked about */
83 /* that's the central struct */
84 struct printer_handle {
85         struct printer_handle *prev, *next;
86         bool document_started;
87         bool page_started;
88         uint32 jobid; /* jobid in printing backend */
89         int printer_type;
90         const char *servername;
91         fstring sharename;
92         uint32 type;
93         uint32 access_granted;
94         struct {
95                 uint32 flags;
96                 uint32 options;
97                 fstring localmachine;
98                 uint32 printerlocal;
99                 struct spoolss_NotifyOption *option;
100                 struct policy_handle cli_hnd;
101                 struct notify_back_channel *cli_chan;
102                 uint32 change;
103                 /* are we in a FindNextPrinterChangeNotify() call? */
104                 bool fnpcn;
105                 struct messaging_context *msg_ctx;
106         } notify;
107         struct {
108                 fstring machine;
109                 fstring user;
110         } client;
111
112         /* devmode sent in the OpenPrinter() call */
113         struct spoolss_DeviceMode *devmode;
114
115         /* TODO cache the printer info2 structure */
116         struct spoolss_PrinterInfo2 *info2;
117
118 };
119
120 static struct printer_handle *printers_list;
121
122 struct printer_session_counter {
123         struct printer_session_counter *next;
124         struct printer_session_counter *prev;
125
126         int snum;
127         uint32_t counter;
128 };
129
130 static struct printer_session_counter *counter_list;
131
132 struct notify_back_channel {
133         struct notify_back_channel *prev, *next;
134
135         /* associated client */
136         struct sockaddr_storage client_address;
137
138         /* print notify back-channel pipe handle*/
139         struct rpc_pipe_client *cli_pipe;
140         uint32_t active_connections;
141 };
142
143 static struct notify_back_channel *back_channels;
144
145 /* Map generic permissions to printer object specific permissions */
146
147 const struct standard_mapping printer_std_mapping = {
148         PRINTER_READ,
149         PRINTER_WRITE,
150         PRINTER_EXECUTE,
151         PRINTER_ALL_ACCESS
152 };
153
154 /* Map generic permissions to print server object specific permissions */
155
156 const struct standard_mapping printserver_std_mapping = {
157         SERVER_READ,
158         SERVER_WRITE,
159         SERVER_EXECUTE,
160         SERVER_ALL_ACCESS
161 };
162
163 /* API table for Xcv Monitor functions */
164
165 struct xcv_api_table {
166         const char *name;
167         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
168 };
169
170 static void prune_printername_cache(void);
171
172 /********************************************************************
173  * Canonicalize servername.
174  ********************************************************************/
175
176 static const char *canon_servername(const char *servername)
177 {
178         const char *pservername = servername;
179         while (*pservername == '\\') {
180                 pservername++;
181         }
182         return pservername;
183 }
184
185 /* translate between internal status numbers and NT status numbers */
186 static int nt_printj_status(int v)
187 {
188         switch (v) {
189         case LPQ_QUEUED:
190                 return 0;
191         case LPQ_PAUSED:
192                 return JOB_STATUS_PAUSED;
193         case LPQ_SPOOLING:
194                 return JOB_STATUS_SPOOLING;
195         case LPQ_PRINTING:
196                 return JOB_STATUS_PRINTING;
197         case LPQ_ERROR:
198                 return JOB_STATUS_ERROR;
199         case LPQ_DELETING:
200                 return JOB_STATUS_DELETING;
201         case LPQ_OFFLINE:
202                 return JOB_STATUS_OFFLINE;
203         case LPQ_PAPEROUT:
204                 return JOB_STATUS_PAPEROUT;
205         case LPQ_PRINTED:
206                 return JOB_STATUS_PRINTED;
207         case LPQ_DELETED:
208                 return JOB_STATUS_DELETED;
209         case LPQ_BLOCKED:
210                 return JOB_STATUS_BLOCKED_DEVQ;
211         case LPQ_USER_INTERVENTION:
212                 return JOB_STATUS_USER_INTERVENTION;
213         }
214         return 0;
215 }
216
217 static int nt_printq_status(int v)
218 {
219         switch (v) {
220         case LPQ_PAUSED:
221                 return PRINTER_STATUS_PAUSED;
222         case LPQ_QUEUED:
223         case LPQ_SPOOLING:
224         case LPQ_PRINTING:
225                 return 0;
226         }
227         return 0;
228 }
229
230 /***************************************************************************
231  Disconnect from the client
232 ****************************************************************************/
233
234 static void srv_spoolss_replycloseprinter(int snum,
235                                           struct printer_handle *prn_hnd)
236 {
237         WERROR result;
238         NTSTATUS status;
239
240         /*
241          * Tell the specific printing tdb we no longer want messages for this printer
242          * by deregistering our PID.
243          */
244
245         if (!print_notify_deregister_pid(snum)) {
246                 DEBUG(0, ("Failed to register our pid for printer %s\n",
247                           lp_const_servicename(snum)));
248         }
249
250         /* weird if the test succeeds !!! */
251         if (prn_hnd->notify.cli_chan == NULL ||
252             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
253             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
254             prn_hnd->notify.cli_chan->active_connections == 0) {
255                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
256                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
257                 TALLOC_FREE(prn_hnd->notify.cli_chan);
258                 return;
259         }
260
261         status = dcerpc_spoolss_ReplyClosePrinter(
262                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
263                                         talloc_tos(),
264                                         &prn_hnd->notify.cli_hnd,
265                                         &result);
266         if (!NT_STATUS_IS_OK(status)) {
267                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
268                           nt_errstr(status)));
269                 result = ntstatus_to_werror(status);
270         } else if (!W_ERROR_IS_OK(result)) {
271                 DEBUG(0, ("reply_close_printer failed [%s].\n",
272                           win_errstr(result)));
273         }
274
275         /* if it's the last connection, deconnect the IPC$ share */
276         if (prn_hnd->notify.cli_chan->active_connections == 1) {
277
278                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
279                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
280                 TALLOC_FREE(prn_hnd->notify.cli_chan);
281
282                 if (prn_hnd->notify.msg_ctx != NULL) {
283                         messaging_deregister(prn_hnd->notify.msg_ctx,
284                                              MSG_PRINTER_NOTIFY2, NULL);
285                 }
286         }
287
288         if (prn_hnd->notify.cli_chan) {
289                 prn_hnd->notify.cli_chan->active_connections--;
290                 prn_hnd->notify.cli_chan = NULL;
291         }
292 }
293
294 /****************************************************************************
295  Functions to free a printer entry datastruct.
296 ****************************************************************************/
297
298 static int printer_entry_destructor(struct printer_handle *Printer)
299 {
300         if (Printer->notify.cli_chan != NULL &&
301             Printer->notify.cli_chan->active_connections > 0) {
302                 int snum = -1;
303
304                 switch(Printer->printer_type) {
305                 case SPLHND_SERVER:
306                         srv_spoolss_replycloseprinter(snum, Printer);
307                         break;
308
309                 case SPLHND_PRINTER:
310                         snum = print_queue_snum(Printer->sharename);
311                         if (snum != -1) {
312                                 srv_spoolss_replycloseprinter(snum, Printer);
313                         }
314                         break;
315                 default:
316                         break;
317                 }
318         }
319
320         Printer->notify.flags=0;
321         Printer->notify.options=0;
322         Printer->notify.localmachine[0]='\0';
323         Printer->notify.printerlocal=0;
324         TALLOC_FREE(Printer->notify.option);
325         TALLOC_FREE(Printer->devmode);
326
327         /* Remove from the internal list. */
328         DLIST_REMOVE(printers_list, Printer);
329         return 0;
330 }
331
332 /****************************************************************************
333   find printer index by handle
334 ****************************************************************************/
335
336 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
337                                                         struct policy_handle *hnd)
338 {
339         struct printer_handle *find_printer = NULL;
340
341         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
342                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
343                 return NULL;
344         }
345
346         return find_printer;
347 }
348
349 /****************************************************************************
350  Close printer index by handle.
351 ****************************************************************************/
352
353 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
354 {
355         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
356
357         if (!Printer) {
358                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
359                         OUR_HANDLE(hnd)));
360                 return false;
361         }
362
363         close_policy_hnd(p, hnd);
364
365         return true;
366 }
367
368 /****************************************************************************
369  Delete a printer given a handle.
370 ****************************************************************************/
371
372 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
373                                   const char *sharename,
374                                   struct messaging_context *msg_ctx)
375 {
376         char *cmd = lp_deleteprinter_cmd();
377         char *command = NULL;
378         int ret;
379         bool is_print_op = false;
380
381         /* can't fail if we don't try */
382
383         if ( !*cmd )
384                 return WERR_OK;
385
386         command = talloc_asprintf(ctx,
387                         "%s \"%s\"",
388                         cmd, sharename);
389         if (!command) {
390                 return WERR_NOMEM;
391         }
392         if ( token )
393                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
394
395         DEBUG(10,("Running [%s]\n", command));
396
397         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
398
399         if ( is_print_op )
400                 become_root();
401
402         if ( (ret = smbrun(command, NULL)) == 0 ) {
403                 /* Tell everyone we updated smb.conf. */
404                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
405         }
406
407         if ( is_print_op )
408                 unbecome_root();
409
410         /********** END SePrintOperatorPrivlege BLOCK **********/
411
412         DEBUGADD(10,("returned [%d]\n", ret));
413
414         TALLOC_FREE(command);
415
416         if (ret != 0)
417                 return WERR_BADFID; /* What to return here? */
418
419         return WERR_OK;
420 }
421
422 /****************************************************************************
423  Delete a printer given a handle.
424 ****************************************************************************/
425
426 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
427 {
428         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
429         WERROR result;
430
431         if (!Printer) {
432                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
433                         OUR_HANDLE(hnd)));
434                 return WERR_BADFID;
435         }
436
437         /*
438          * It turns out that Windows allows delete printer on a handle
439          * opened by an admin user, then used on a pipe handle created
440          * by an anonymous user..... but they're working on security.... riiight !
441          * JRA.
442          */
443
444         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
445                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
446                 return WERR_ACCESS_DENIED;
447         }
448
449         /* this does not need a become root since the access check has been
450            done on the handle already */
451
452         result = winreg_delete_printer_key_internal(p->mem_ctx,
453                                            get_session_info_system(),
454                                            p->msg_ctx,
455                                            Printer->sharename,
456                                            "");
457         if (!W_ERROR_IS_OK(result)) {
458                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
459                 return WERR_BADFID;
460         }
461
462         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
463                                      Printer->sharename, p->msg_ctx);
464         if (!W_ERROR_IS_OK(result)) {
465                 return result;
466         }
467         prune_printername_cache();
468         return WERR_OK;
469 }
470
471 /****************************************************************************
472  Return the snum of a printer corresponding to an handle.
473 ****************************************************************************/
474
475 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
476                              int *number, struct share_params **params)
477 {
478         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
479
480         if (!Printer) {
481                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
482                         OUR_HANDLE(hnd)));
483                 return false;
484         }
485
486         switch (Printer->printer_type) {
487                 case SPLHND_PRINTER:
488                         DEBUG(4,("short name:%s\n", Printer->sharename));
489                         *number = print_queue_snum(Printer->sharename);
490                         return (*number != -1);
491                 case SPLHND_SERVER:
492                         return false;
493                 default:
494                         return false;
495         }
496 }
497
498 /****************************************************************************
499  Set printer handle type.
500  Check if it's \\server or \\server\printer
501 ****************************************************************************/
502
503 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
504 {
505         DEBUG(3,("Setting printer type=%s\n", handlename));
506
507         /* it's a print server */
508         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
509                 DEBUGADD(4,("Printer is a print server\n"));
510                 Printer->printer_type = SPLHND_SERVER;
511         }
512         /* it's a printer (set_printer_hnd_name() will handle port monitors */
513         else {
514                 DEBUGADD(4,("Printer is a printer\n"));
515                 Printer->printer_type = SPLHND_PRINTER;
516         }
517
518         return true;
519 }
520
521 static void prune_printername_cache_fn(const char *key, const char *value,
522                                        time_t timeout, void *private_data)
523 {
524         gencache_del(key);
525 }
526
527 static void prune_printername_cache(void)
528 {
529         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
530 }
531
532 /****************************************************************************
533  Set printer handle name..  Accept names like \\server, \\server\printer,
534  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
535  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
536  XcvDataPort() interface.
537 ****************************************************************************/
538
539 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
540                                    const struct auth_session_info *session_info,
541                                    struct messaging_context *msg_ctx,
542                                    struct printer_handle *Printer,
543                                    const char *handlename)
544 {
545         int snum;
546         int n_services=lp_numservices();
547         char *aprinter;
548         const char *printername;
549         const char *servername = NULL;
550         fstring sname;
551         bool found = false;
552         struct spoolss_PrinterInfo2 *info2 = NULL;
553         WERROR result;
554         char *p;
555
556         /*
557          * Hopefully nobody names his printers like this. Maybe \ or ,
558          * are illegal in printer names even?
559          */
560         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
561         char *cache_key;
562         char *tmp;
563
564         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
565                 (unsigned long)strlen(handlename)));
566
567         aprinter = discard_const_p(char, handlename);
568         if ( *handlename == '\\' ) {
569                 servername = canon_servername(handlename);
570                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
571                         *aprinter = '\0';
572                         aprinter++;
573                 }
574                 if (!is_myname_or_ipaddr(servername)) {
575                         return WERR_INVALID_PRINTER_NAME;
576                 }
577                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
578                 if (Printer->servername == NULL) {
579                         return WERR_NOMEM;
580                 }
581         }
582
583         if (Printer->printer_type == SPLHND_SERVER) {
584                 return WERR_OK;
585         }
586
587         if (Printer->printer_type != SPLHND_PRINTER) {
588                 return WERR_INVALID_HANDLE;
589         }
590
591         DEBUGADD(5, ("searching for [%s]\n", aprinter));
592
593         p = strchr(aprinter, ',');
594         if (p != NULL) {
595                 char *p2 = p;
596                 p++;
597                 if (*p == ' ') {
598                         p++;
599                 }
600                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
601                         *p2 = '\0';
602                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
603                         *p2 = '\0';
604                 }
605         }
606
607         if (p) {
608                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
609         }
610
611         /* check for the Port Monitor Interface */
612         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
613                 Printer->printer_type = SPLHND_PORTMON_TCP;
614                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
615                 found = true;
616         }
617         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
618                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
619                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
620                 found = true;
621         }
622
623         /*
624          * With hundreds of printers, the "for" loop iterating all
625          * shares can be quite expensive, as it is done on every
626          * OpenPrinter. The loop maps "aprinter" to "sname", the
627          * result of which we cache in gencache.
628          */
629
630         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
631                                     aprinter);
632         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
633
634                 found = (strcmp(tmp, printer_not_found) != 0);
635                 if (!found) {
636                         DEBUG(4, ("Printer %s not found\n", aprinter));
637                         SAFE_FREE(tmp);
638                         return WERR_INVALID_PRINTER_NAME;
639                 }
640                 fstrcpy(sname, tmp);
641                 SAFE_FREE(tmp);
642         }
643
644         /* Search all sharenames first as this is easier than pulling
645            the printer_info_2 off of disk. Don't use find_service() since
646            that calls out to map_username() */
647
648         /* do another loop to look for printernames */
649         for (snum = 0; !found && snum < n_services; snum++) {
650                 const char *printer = lp_const_servicename(snum);
651
652                 /* no point going on if this is not a printer */
653                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
654                         continue;
655                 }
656
657                 /* ignore [printers] share */
658                 if (strequal(printer, "printers")) {
659                         continue;
660                 }
661
662                 fstrcpy(sname, printer);
663                 if (strequal(aprinter, printer)) {
664                         found = true;
665                         break;
666                 }
667
668                 /* no point looking up the printer object if
669                    we aren't allowing printername != sharename */
670                 if (lp_force_printername(snum)) {
671                         continue;
672                 }
673
674                 result = winreg_get_printer_internal(mem_ctx,
675                                             session_info,
676                                             msg_ctx,
677                                             sname,
678                                             &info2);
679                 if ( !W_ERROR_IS_OK(result) ) {
680                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
681                                  sname, win_errstr(result)));
682                         continue;
683                 }
684
685                 printername = strrchr(info2->printername, '\\');
686                 if (printername == NULL) {
687                         printername = info2->printername;
688                 } else {
689                         printername++;
690                 }
691
692                 if (strequal(printername, aprinter)) {
693                         found = true;
694                         break;
695                 }
696
697                 DEBUGADD(10, ("printername: %s\n", printername));
698
699                 TALLOC_FREE(info2);
700         }
701
702         if ( !found ) {
703                 if (cache_key != NULL) {
704                         gencache_set(cache_key, printer_not_found,
705                                      time(NULL)+300);
706                         TALLOC_FREE(cache_key);
707                 }
708                 DEBUGADD(4,("Printer not found\n"));
709                 return WERR_INVALID_PRINTER_NAME;
710         }
711
712         if (cache_key != NULL) {
713                 gencache_set(cache_key, sname, time(NULL)+300);
714                 TALLOC_FREE(cache_key);
715         }
716
717         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
718
719         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
720
721         return WERR_OK;
722 }
723
724 /****************************************************************************
725  Find first available printer slot. creates a printer handle for you.
726  ****************************************************************************/
727
728 static WERROR open_printer_hnd(struct pipes_struct *p,
729                                struct policy_handle *hnd,
730                                const char *name,
731                                uint32_t access_granted)
732 {
733         struct printer_handle *new_printer;
734         WERROR result;
735
736         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
737
738         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
739         if (new_printer == NULL) {
740                 return WERR_NOMEM;
741         }
742         talloc_set_destructor(new_printer, printer_entry_destructor);
743
744         /* This also steals the printer_handle on the policy_handle */
745         if (!create_policy_hnd(p, hnd, new_printer)) {
746                 TALLOC_FREE(new_printer);
747                 return WERR_INVALID_HANDLE;
748         }
749
750         /* Add to the internal list. */
751         DLIST_ADD(printers_list, new_printer);
752
753         new_printer->notify.option=NULL;
754
755         if (!set_printer_hnd_printertype(new_printer, name)) {
756                 close_printer_handle(p, hnd);
757                 return WERR_INVALID_HANDLE;
758         }
759
760         result = set_printer_hnd_name(p->mem_ctx,
761                                       get_session_info_system(),
762                                       p->msg_ctx,
763                                       new_printer, name);
764         if (!W_ERROR_IS_OK(result)) {
765                 close_printer_handle(p, hnd);
766                 return result;
767         }
768
769         new_printer->access_granted = access_granted;
770
771         DEBUG(5, ("%d printer handles active\n",
772                   (int)num_pipe_handles(p)));
773
774         return WERR_OK;
775 }
776
777 /***************************************************************************
778  check to see if the client motify handle is monitoring the notification
779  given by (notify_type, notify_field).
780  **************************************************************************/
781
782 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
783                                       uint16_t notify_field)
784 {
785         return true;
786 }
787
788 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
789                                 uint16_t notify_field)
790 {
791         struct spoolss_NotifyOption *option = p->notify.option;
792         uint32_t i, j;
793
794         /*
795          * Flags should always be zero when the change notify
796          * is registered by the client's spooler.  A user Win32 app
797          * might use the flags though instead of the NOTIFY_OPTION_INFO
798          * --jerry
799          */
800
801         if (!option) {
802                 return false;
803         }
804
805         if (p->notify.flags)
806                 return is_monitoring_event_flags(
807                         p->notify.flags, notify_type, notify_field);
808
809         for (i = 0; i < option->count; i++) {
810
811                 /* Check match for notify_type */
812
813                 if (option->types[i].type != notify_type)
814                         continue;
815
816                 /* Check match for field */
817
818                 for (j = 0; j < option->types[i].count; j++) {
819                         if (option->types[i].fields[j].field == notify_field) {
820                                 return true;
821                         }
822                 }
823         }
824
825         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
826                    p->servername, p->sharename, notify_type, notify_field));
827
828         return false;
829 }
830
831 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
832         _data->data.integer[0] = _integer; \
833         _data->data.integer[1] = 0;
834
835
836 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
837         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
838         if (!_data->data.string.string) {\
839                 _data->data.string.size = 0; \
840         } \
841         _data->data.string.size = strlen_m_term(_p) * 2;
842
843 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
844         _data->data.devmode.devmode = _devmode;
845
846 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
847         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
848         if (!_data->data.sd.sd) { \
849                 _data->data.sd.sd_size = 0; \
850         } \
851         _data->data.sd.sd_size = \
852                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
853
854 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
855                                    struct tm *t,
856                                    const char **pp,
857                                    uint32_t *plen)
858 {
859         struct spoolss_Time st;
860         uint32_t len = 16;
861         char *p;
862
863         if (!init_systemtime(&st, t)) {
864                 return;
865         }
866
867         p = talloc_array(mem_ctx, char, len);
868         if (!p) {
869                 return;
870         }
871
872         /*
873          * Systemtime must be linearized as a set of UINT16's.
874          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
875          */
876
877         SSVAL(p, 0, st.year);
878         SSVAL(p, 2, st.month);
879         SSVAL(p, 4, st.day_of_week);
880         SSVAL(p, 6, st.day);
881         SSVAL(p, 8, st.hour);
882         SSVAL(p, 10, st.minute);
883         SSVAL(p, 12, st.second);
884         SSVAL(p, 14, st.millisecond);
885
886         *pp = p;
887         *plen = len;
888 }
889
890 /* Convert a notification message to a struct spoolss_Notify */
891
892 static void notify_one_value(struct spoolss_notify_msg *msg,
893                              struct spoolss_Notify *data,
894                              TALLOC_CTX *mem_ctx)
895 {
896         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
897 }
898
899 static void notify_string(struct spoolss_notify_msg *msg,
900                           struct spoolss_Notify *data,
901                           TALLOC_CTX *mem_ctx)
902 {
903         /* The length of the message includes the trailing \0 */
904
905         data->data.string.size = msg->len * 2;
906         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
907         if (!data->data.string.string) {
908                 data->data.string.size = 0;
909                 return;
910         }
911 }
912
913 static void notify_system_time(struct spoolss_notify_msg *msg,
914                                struct spoolss_Notify *data,
915                                TALLOC_CTX *mem_ctx)
916 {
917         data->data.string.string = NULL;
918         data->data.string.size = 0;
919
920         if (msg->len != sizeof(time_t)) {
921                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
922                           msg->len));
923                 return;
924         }
925
926         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
927                                &data->data.string.string,
928                                &data->data.string.size);
929 }
930
931 struct notify2_message_table {
932         const char *name;
933         void (*fn)(struct spoolss_notify_msg *msg,
934                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
935 };
936
937 static struct notify2_message_table printer_notify_table[] = {
938         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
939         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
940         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
941         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
942         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
943         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
944         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
945         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
946         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
947         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
948         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
949         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
950         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
951         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
952         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
953         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
954         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
955         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
956         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
957 };
958
959 static struct notify2_message_table job_notify_table[] = {
960         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
961         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
962         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
963         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
964         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
965         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
966         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
967         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
968         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
969         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
970         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
971         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
972         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
973         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
974         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
975         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
976         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
977         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
978         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
979         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
980         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
981         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
982         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
983         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
984 };
985
986
987 /***********************************************************************
988  Allocate talloc context for container object
989  **********************************************************************/
990
991 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
992 {
993         if ( !ctr )
994                 return;
995
996         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
997
998         return;
999 }
1000
1001 /***********************************************************************
1002  release all allocated memory and zero out structure
1003  **********************************************************************/
1004
1005 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1006 {
1007         if ( !ctr )
1008                 return;
1009
1010         if ( ctr->ctx )
1011                 talloc_destroy(ctr->ctx);
1012
1013         ZERO_STRUCTP(ctr);
1014
1015         return;
1016 }
1017
1018 /***********************************************************************
1019  **********************************************************************/
1020
1021 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1022 {
1023         if ( !ctr )
1024                 return NULL;
1025
1026         return ctr->ctx;
1027 }
1028
1029 /***********************************************************************
1030  **********************************************************************/
1031
1032 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1033 {
1034         if ( !ctr || !ctr->msg_groups )
1035                 return NULL;
1036
1037         if ( idx >= ctr->num_groups )
1038                 return NULL;
1039
1040         return &ctr->msg_groups[idx];
1041
1042 }
1043
1044 /***********************************************************************
1045  How many groups of change messages do we have ?
1046  **********************************************************************/
1047
1048 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1049 {
1050         if ( !ctr )
1051                 return 0;
1052
1053         return ctr->num_groups;
1054 }
1055
1056 /***********************************************************************
1057  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1058  **********************************************************************/
1059
1060 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1061 {
1062         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1063         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1064         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1065         int                             i, new_slot;
1066
1067         if ( !ctr || !msg )
1068                 return 0;
1069
1070         /* loop over all groups looking for a matching printer name */
1071
1072         for ( i=0; i<ctr->num_groups; i++ ) {
1073                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1074                         break;
1075         }
1076
1077         /* add a new group? */
1078
1079         if ( i == ctr->num_groups ) {
1080                 ctr->num_groups++;
1081
1082                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1083                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1084                         return 0;
1085                 }
1086                 ctr->msg_groups = groups;
1087
1088                 /* clear the new entry and set the printer name */
1089
1090                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1091                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1092         }
1093
1094         /* add the change messages; 'i' is the correct index now regardless */
1095
1096         msg_grp = &ctr->msg_groups[i];
1097
1098         msg_grp->num_msgs++;
1099
1100         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1101                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1102                 return 0;
1103         }
1104         msg_grp->msgs = msg_list;
1105
1106         new_slot = msg_grp->num_msgs-1;
1107         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1108
1109         /* need to allocate own copy of data */
1110
1111         if ( msg->len != 0 )
1112                 msg_grp->msgs[new_slot].notify.data = (char *)
1113                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1114
1115         return ctr->num_groups;
1116 }
1117
1118 static void construct_info_data(struct spoolss_Notify *info_data,
1119                                 enum spoolss_NotifyType type,
1120                                 uint16_t field, int id);
1121
1122 /***********************************************************************
1123  Send a change notication message on all handles which have a call
1124  back registered
1125  **********************************************************************/
1126
1127 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1128                                   struct printer_handle *prn_hnd,
1129                                   SPOOLSS_NOTIFY_MSG *messages,
1130                                   uint32_t num_msgs,
1131                                   struct spoolss_Notify **_notifies,
1132                                   int *_count)
1133 {
1134         struct spoolss_Notify *notifies;
1135         SPOOLSS_NOTIFY_MSG *msg;
1136         int count = 0;
1137         uint32_t id;
1138         int i;
1139
1140         notifies = talloc_zero_array(mem_ctx,
1141                                      struct spoolss_Notify, num_msgs);
1142         if (!notifies) {
1143                 return ENOMEM;
1144         }
1145
1146         for (i = 0; i < num_msgs; i++) {
1147
1148                 msg = &messages[i];
1149
1150                 /* Are we monitoring this event? */
1151
1152                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1153                         continue;
1154                 }
1155
1156                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1157                            "for printer [%s]\n",
1158                            msg->type, msg->field, prn_hnd->sharename));
1159
1160                 /*
1161                  * if the is a printer notification handle and not a job
1162                  * notification type, then set the id to 0.
1163                  * Otherwise just use what was specified in the message.
1164                  *
1165                  * When registering change notification on a print server
1166                  * handle we always need to send back the id (snum) matching
1167                  * the printer for which the change took place.
1168                  * For change notify registered on a printer handle,
1169                  * this does not matter and the id should be 0.
1170                  *
1171                  * --jerry
1172                  */
1173
1174                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1175                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1176                         id = 0;
1177                 } else {
1178                         id = msg->id;
1179                 }
1180
1181                 /* Convert unix jobid to smb jobid */
1182
1183                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1184                         id = sysjob_to_jobid(msg->id);
1185
1186                         if (id == -1) {
1187                                 DEBUG(3, ("no such unix jobid %d\n",
1188                                           msg->id));
1189                                 continue;
1190                         }
1191                 }
1192
1193                 construct_info_data(&notifies[count],
1194                                     msg->type, msg->field, id);
1195
1196                 switch(msg->type) {
1197                 case PRINTER_NOTIFY_TYPE:
1198                         if (printer_notify_table[msg->field].fn) {
1199                                 printer_notify_table[msg->field].fn(msg,
1200                                                 &notifies[count], mem_ctx);
1201                         }
1202                         break;
1203
1204                 case JOB_NOTIFY_TYPE:
1205                         if (job_notify_table[msg->field].fn) {
1206                                 job_notify_table[msg->field].fn(msg,
1207                                                 &notifies[count], mem_ctx);
1208                         }
1209                         break;
1210
1211                 default:
1212                         DEBUG(5, ("Unknown notification type %d\n",
1213                                   msg->type));
1214                         continue;
1215                 }
1216
1217                 count++;
1218         }
1219
1220         *_notifies = notifies;
1221         *_count = count;
1222
1223         return 0;
1224 }
1225
1226 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1227                                 struct printer_handle *prn_hnd,
1228                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1229 {
1230         struct spoolss_Notify *notifies;
1231         int count = 0;
1232         union spoolss_ReplyPrinterInfo info;
1233         struct spoolss_NotifyInfo info0;
1234         uint32_t reply_result;
1235         NTSTATUS status;
1236         WERROR werr;
1237         int ret;
1238
1239         /* Is there notification on this handle? */
1240         if (prn_hnd->notify.cli_chan == NULL ||
1241             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1242             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1243             prn_hnd->notify.cli_chan->active_connections == 0) {
1244                 return 0;
1245         }
1246
1247         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1248                    prn_hnd->servername, prn_hnd->sharename));
1249
1250         /* For this printer? Print servers always receive notifications. */
1251         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1252             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1253                 return 0;
1254         }
1255
1256         DEBUG(10,("Our printer\n"));
1257
1258         /* build the array of change notifications */
1259         ret = build_notify2_messages(mem_ctx, prn_hnd,
1260                                      msg_group->msgs,
1261                                      msg_group->num_msgs,
1262                                      &notifies, &count);
1263         if (ret) {
1264                 return ret;
1265         }
1266
1267         info0.version   = 0x2;
1268         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1269         info0.count     = count;
1270         info0.notifies  = notifies;
1271
1272         info.info0 = &info0;
1273
1274         status = dcerpc_spoolss_RouterReplyPrinterEx(
1275                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1276                                 mem_ctx,
1277                                 &prn_hnd->notify.cli_hnd,
1278                                 prn_hnd->notify.change, /* color */
1279                                 prn_hnd->notify.flags,
1280                                 &reply_result,
1281                                 0, /* reply_type, must be 0 */
1282                                 info, &werr);
1283         if (!NT_STATUS_IS_OK(status)) {
1284                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1285                           "failed: %s\n",
1286                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1287                           nt_errstr(status)));
1288                 werr = ntstatus_to_werror(status);
1289         } else if (!W_ERROR_IS_OK(werr)) {
1290                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1291                           "failed: %s\n",
1292                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1293                           win_errstr(werr)));
1294         }
1295         switch (reply_result) {
1296         case 0:
1297                 break;
1298         case PRINTER_NOTIFY_INFO_DISCARDED:
1299         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1300         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1301                 break;
1302         default:
1303                 break;
1304         }
1305
1306         return 0;
1307 }
1308
1309 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1310 {
1311         struct printer_handle    *p;
1312         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1313         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1314         int ret;
1315
1316         if ( !msg_group ) {
1317                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1318                 return;
1319         }
1320
1321         if (!msg_group->msgs) {
1322                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1323                 return;
1324         }
1325
1326         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1327
1328         /* loop over all printers */
1329
1330         for (p = printers_list; p; p = p->next) {
1331                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1332                 if (ret) {
1333                         goto done;
1334                 }
1335         }
1336
1337 done:
1338         DEBUG(8,("send_notify2_changes: Exit...\n"));
1339         return;
1340 }
1341
1342 /***********************************************************************
1343  **********************************************************************/
1344
1345 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1346 {
1347
1348         uint32_t tv_sec, tv_usec;
1349         size_t offset = 0;
1350
1351         /* Unpack message */
1352
1353         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1354                              msg->printer);
1355
1356         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1357                                 &tv_sec, &tv_usec,
1358                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1359
1360         if (msg->len == 0)
1361                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1362                            &msg->notify.value[0], &msg->notify.value[1]);
1363         else
1364                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1365                            &msg->len, &msg->notify.data);
1366
1367         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1368                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1369
1370         tv->tv_sec = tv_sec;
1371         tv->tv_usec = tv_usec;
1372
1373         if (msg->len == 0)
1374                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1375                           msg->notify.value[1]));
1376         else
1377                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1378
1379         return true;
1380 }
1381
1382 /********************************************************************
1383  Receive a notify2 message list
1384  ********************************************************************/
1385
1386 static void receive_notify2_message_list(struct messaging_context *msg,
1387                                          void *private_data,
1388                                          uint32_t msg_type,
1389                                          struct server_id server_id,
1390                                          DATA_BLOB *data)
1391 {
1392         size_t                  msg_count, i;
1393         char                    *buf = (char *)data->data;
1394         char                    *msg_ptr;
1395         size_t                  msg_len;
1396         SPOOLSS_NOTIFY_MSG      notify;
1397         SPOOLSS_NOTIFY_MSG_CTR  messages;
1398         int                     num_groups;
1399
1400         if (data->length < 4) {
1401                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1402                 return;
1403         }
1404
1405         msg_count = IVAL(buf, 0);
1406         msg_ptr = buf + 4;
1407
1408         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1409
1410         if (msg_count == 0) {
1411                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1412                 return;
1413         }
1414
1415         /* initialize the container */
1416
1417         ZERO_STRUCT( messages );
1418         notify_msg_ctr_init( &messages );
1419
1420         /*
1421          * build message groups for each printer identified
1422          * in a change_notify msg.  Remember that a PCN message
1423          * includes the handle returned for the srv_spoolss_replyopenprinter()
1424          * call.  Therefore messages are grouped according to printer handle.
1425          */
1426
1427         for ( i=0; i<msg_count; i++ ) {
1428                 struct timeval msg_tv;
1429
1430                 if (msg_ptr + 4 - buf > data->length) {
1431                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1432                         return;
1433                 }
1434
1435                 msg_len = IVAL(msg_ptr,0);
1436                 msg_ptr += 4;
1437
1438                 if (msg_ptr + msg_len - buf > data->length) {
1439                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1440                         return;
1441                 }
1442
1443                 /* unpack messages */
1444
1445                 ZERO_STRUCT( notify );
1446                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1447                 msg_ptr += msg_len;
1448
1449                 /* add to correct list in container */
1450
1451                 notify_msg_ctr_addmsg( &messages, &notify );
1452
1453                 /* free memory that might have been allocated by notify2_unpack_msg() */
1454
1455                 if ( notify.len != 0 )
1456                         SAFE_FREE( notify.notify.data );
1457         }
1458
1459         /* process each group of messages */
1460
1461         num_groups = notify_msg_ctr_numgroups( &messages );
1462         for ( i=0; i<num_groups; i++ )
1463                 send_notify2_changes( &messages, i );
1464
1465
1466         /* cleanup */
1467
1468         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1469                 (uint32_t)msg_count ));
1470
1471         notify_msg_ctr_destroy( &messages );
1472
1473         return;
1474 }
1475
1476 /********************************************************************
1477  Send a message to ourself about new driver being installed
1478  so we can upgrade the information for each printer bound to this
1479  driver
1480  ********************************************************************/
1481
1482 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1483                                             struct messaging_context *msg_ctx)
1484 {
1485         int len = strlen(drivername);
1486
1487         if (!len)
1488                 return false;
1489
1490         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1491                 drivername));
1492
1493         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1494                            MSG_PRINTER_DRVUPGRADE,
1495                            (const uint8_t *)drivername, len+1);
1496
1497         return true;
1498 }
1499
1500 void srv_spoolss_cleanup(void)
1501 {
1502         struct printer_session_counter *session_counter;
1503
1504         for (session_counter = counter_list;
1505              session_counter != NULL;
1506              session_counter = counter_list) {
1507                 DLIST_REMOVE(counter_list, session_counter);
1508                 TALLOC_FREE(session_counter);
1509         }
1510 }
1511
1512 /**********************************************************************
1513  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1514  over all printers, upgrading ones as necessary
1515  **********************************************************************/
1516
1517 void do_drv_upgrade_printer(struct messaging_context *msg,
1518                             void *private_data,
1519                             uint32_t msg_type,
1520                             struct server_id server_id,
1521                             DATA_BLOB *data)
1522 {
1523         TALLOC_CTX *tmp_ctx;
1524         const struct auth_session_info *session_info = get_session_info_system();
1525         struct spoolss_PrinterInfo2 *pinfo2;
1526         WERROR result;
1527         const char *drivername;
1528         int snum;
1529         int n_services = lp_numservices();
1530         struct dcerpc_binding_handle *b = NULL;
1531
1532         tmp_ctx = talloc_new(NULL);
1533         if (!tmp_ctx) return;
1534
1535         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1536         if (!drivername) {
1537                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1538                 goto done;
1539         }
1540
1541         DEBUG(10, ("do_drv_upgrade_printer: "
1542                    "Got message for new driver [%s]\n", drivername));
1543
1544         /* Iterate the printer list */
1545
1546         for (snum = 0; snum < n_services; snum++) {
1547                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1548                         continue;
1549                 }
1550
1551                 /* ignore [printers] share */
1552                 if (strequal(lp_const_servicename(snum), "printers")) {
1553                         continue;
1554                 }
1555
1556                 if (b == NULL) {
1557                         result = winreg_printer_binding_handle(tmp_ctx,
1558                                                                session_info,
1559                                                                msg,
1560                                                                &b);
1561                         if (!W_ERROR_IS_OK(result)) {
1562                                 break;
1563                         }
1564                 }
1565
1566                 result = winreg_get_printer(tmp_ctx, b,
1567                                             lp_const_servicename(snum),
1568                                             &pinfo2);
1569
1570                 if (!W_ERROR_IS_OK(result)) {
1571                         continue;
1572                 }
1573
1574                 if (!pinfo2->drivername) {
1575                         continue;
1576                 }
1577
1578                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1579                         continue;
1580                 }
1581
1582                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1583
1584                 /* all we care about currently is the change_id */
1585                 result = winreg_printer_update_changeid(tmp_ctx, b,
1586                                                         pinfo2->printername);
1587
1588                 if (!W_ERROR_IS_OK(result)) {
1589                         DEBUG(3, ("do_drv_upgrade_printer: "
1590                                   "Failed to update changeid [%s]\n",
1591                                   win_errstr(result)));
1592                 }
1593         }
1594
1595         /* all done */
1596 done:
1597         talloc_free(tmp_ctx);
1598 }
1599
1600 /********************************************************************
1601  Update the cache for all printq's with a registered client
1602  connection
1603  ********************************************************************/
1604
1605 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1606 {
1607         struct printer_handle *printer = printers_list;
1608         int snum;
1609
1610         /* loop through all printers and update the cache where
1611            a client is connected */
1612         while (printer) {
1613                 if ((printer->printer_type == SPLHND_PRINTER) &&
1614                     ((printer->notify.cli_chan != NULL) &&
1615                      (printer->notify.cli_chan->active_connections > 0))) {
1616                         snum = print_queue_snum(printer->sharename);
1617                         print_queue_status(msg_ctx, snum, NULL, NULL);
1618                 }
1619
1620                 printer = printer->next;
1621         }
1622
1623         return;
1624 }
1625
1626 /****************************************************************
1627  _spoolss_OpenPrinter
1628 ****************************************************************/
1629
1630 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1631                             struct spoolss_OpenPrinter *r)
1632 {
1633         struct spoolss_OpenPrinterEx e;
1634         WERROR werr;
1635
1636         ZERO_STRUCT(e.in.userlevel);
1637
1638         e.in.printername        = r->in.printername;
1639         e.in.datatype           = r->in.datatype;
1640         e.in.devmode_ctr        = r->in.devmode_ctr;
1641         e.in.access_mask        = r->in.access_mask;
1642         e.in.level              = 0;
1643
1644         e.out.handle            = r->out.handle;
1645
1646         werr = _spoolss_OpenPrinterEx(p, &e);
1647
1648         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1649                 /* OpenPrinterEx returns this for a bad
1650                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1651                  * instead.
1652                  */
1653                 werr = WERR_INVALID_PRINTER_NAME;
1654         }
1655
1656         return werr;
1657 }
1658
1659 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1660                               struct spoolss_DeviceMode *orig,
1661                               struct spoolss_DeviceMode **dest)
1662 {
1663         struct spoolss_DeviceMode *dm;
1664
1665         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1666         if (!dm) {
1667                 return WERR_NOMEM;
1668         }
1669
1670         /* copy all values, then duplicate strings and structs */
1671         *dm = *orig;
1672
1673         dm->devicename = talloc_strdup(dm, orig->devicename);
1674         if (!dm->devicename) {
1675                 return WERR_NOMEM;
1676         }
1677         dm->formname = talloc_strdup(dm, orig->formname);
1678         if (!dm->formname) {
1679                 return WERR_NOMEM;
1680         }
1681         if (orig->driverextra_data.data) {
1682                 dm->driverextra_data.data =
1683                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1684                                         orig->driverextra_data.length);
1685                 if (!dm->driverextra_data.data) {
1686                         return WERR_NOMEM;
1687                 }
1688         }
1689
1690         *dest = dm;
1691         return WERR_OK;
1692 }
1693
1694 /****************************************************************
1695  _spoolss_OpenPrinterEx
1696 ****************************************************************/
1697
1698 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1699                               struct spoolss_OpenPrinterEx *r)
1700 {
1701         int snum;
1702         char *raddr;
1703         char *rhost;
1704         struct printer_handle *Printer=NULL;
1705         WERROR result;
1706         int rc;
1707
1708         if (!r->in.printername) {
1709                 return WERR_INVALID_PARAM;
1710         }
1711
1712         if (!*r->in.printername) {
1713                 return WERR_INVALID_PARAM;
1714         }
1715
1716         if (r->in.level > 3) {
1717                 return WERR_INVALID_PARAM;
1718         }
1719         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1720             (r->in.level == 2 && !r->in.userlevel.level2) ||
1721             (r->in.level == 3 && !r->in.userlevel.level3)) {
1722                 return WERR_INVALID_PARAM;
1723         }
1724
1725         /* some sanity check because you can open a printer or a print server */
1726         /* aka: \\server\printer or \\server */
1727
1728         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1729
1730         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1731         if (!W_ERROR_IS_OK(result)) {
1732                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1733                         "for printer %s\n", r->in.printername));
1734                 ZERO_STRUCTP(r->out.handle);
1735                 return result;
1736         }
1737
1738         Printer = find_printer_index_by_hnd(p, r->out.handle);
1739         if ( !Printer ) {
1740                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1741                         "handle we created for printer %s\n", r->in.printername));
1742                 close_printer_handle(p, r->out.handle);
1743                 ZERO_STRUCTP(r->out.handle);
1744                 return WERR_INVALID_PARAM;
1745         }
1746
1747         /*
1748          * First case: the user is opening the print server:
1749          *
1750          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1751          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1752          *
1753          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1754          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1755          * or if the user is listed in the smb.conf printer admin parameter.
1756          *
1757          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1758          * client view printer folder, but does not show the MSAPW.
1759          *
1760          * Note: this test needs code to check access rights here too. Jeremy
1761          * could you look at this?
1762          *
1763          * Second case: the user is opening a printer:
1764          * NT doesn't let us connect to a printer if the connecting user
1765          * doesn't have print permission.
1766          *
1767          * Third case: user is opening a Port Monitor
1768          * access checks same as opening a handle to the print server.
1769          */
1770
1771         switch (Printer->printer_type )
1772         {
1773         case SPLHND_SERVER:
1774         case SPLHND_PORTMON_TCP:
1775         case SPLHND_PORTMON_LOCAL:
1776                 /* Printserver handles use global struct... */
1777
1778                 snum = -1;
1779
1780                 /* Map standard access rights to object specific access rights */
1781
1782                 se_map_standard(&r->in.access_mask,
1783                                 &printserver_std_mapping);
1784
1785                 /* Deny any object specific bits that don't apply to print
1786                    servers (i.e printer and job specific bits) */
1787
1788                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1789
1790                 if (r->in.access_mask &
1791                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1792                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1793                         close_printer_handle(p, r->out.handle);
1794                         ZERO_STRUCTP(r->out.handle);
1795                         return WERR_ACCESS_DENIED;
1796                 }
1797
1798                 /* Allow admin access */
1799
1800                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1801                 {
1802                         if (!lp_ms_add_printer_wizard()) {
1803                                 close_printer_handle(p, r->out.handle);
1804                                 ZERO_STRUCTP(r->out.handle);
1805                                 return WERR_ACCESS_DENIED;
1806                         }
1807
1808                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1809                            and not a printer admin, then fail */
1810
1811                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1812                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1813                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1814                             !token_contains_name_in_list(
1815                                     uidtoname(p->session_info->unix_token->uid),
1816                                     p->session_info->info->domain_name,
1817                                     NULL,
1818                                     p->session_info->security_token,
1819                                     lp_printer_admin(snum))) {
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) {
1947                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1948                                 &Printer->devmode);
1949          }
1950
1951 #if 0   /* JERRY -- I'm doubtful this is really effective */
1952         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1953            optimization in Windows 2000 clients  --jerry */
1954
1955         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1956                 && (RA_WIN2K == get_remote_arch()) )
1957         {
1958                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1959                 usleep( 500000 );
1960         }
1961 #endif
1962
1963         return WERR_OK;
1964 }
1965
1966 /****************************************************************
1967  _spoolss_ClosePrinter
1968 ****************************************************************/
1969
1970 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1971                              struct spoolss_ClosePrinter *r)
1972 {
1973         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1974
1975         if (Printer && Printer->document_started) {
1976                 struct spoolss_EndDocPrinter e;
1977
1978                 e.in.handle = r->in.handle;
1979
1980                 _spoolss_EndDocPrinter(p, &e);
1981         }
1982
1983         if (!close_printer_handle(p, r->in.handle))
1984                 return WERR_BADFID;
1985
1986         /* clear the returned printer handle.  Observed behavior
1987            from Win2k server.  Don't think this really matters.
1988            Previous code just copied the value of the closed
1989            handle.    --jerry */
1990
1991         ZERO_STRUCTP(r->out.handle);
1992
1993         return WERR_OK;
1994 }
1995
1996 /****************************************************************
1997  _spoolss_DeletePrinter
1998 ****************************************************************/
1999
2000 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
2001                               struct spoolss_DeletePrinter *r)
2002 {
2003         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2004         WERROR result;
2005         int snum;
2006
2007         if (Printer && Printer->document_started) {
2008                 struct spoolss_EndDocPrinter e;
2009
2010                 e.in.handle = r->in.handle;
2011
2012                 _spoolss_EndDocPrinter(p, &e);
2013         }
2014
2015         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2016                 winreg_delete_printer_key_internal(p->mem_ctx,
2017                                           get_session_info_system(),
2018                                           p->msg_ctx,
2019                                           lp_const_servicename(snum),
2020                                           "");
2021         }
2022
2023         result = delete_printer_handle(p, r->in.handle);
2024
2025         return result;
2026 }
2027
2028 /*******************************************************************
2029  * static function to lookup the version id corresponding to an
2030  * long architecture string
2031  ******************************************************************/
2032
2033 static const struct print_architecture_table_node archi_table[]= {
2034
2035         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2036         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2037         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2038         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2039         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2040         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2041         {"Windows x64",          SPL_ARCH_X64,          3 },
2042         {NULL,                   "",            -1 }
2043 };
2044
2045 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2046                                    SPOOLSS_DRIVER_VERSION_NT35,
2047                                    SPOOLSS_DRIVER_VERSION_NT4,
2048                                    SPOOLSS_DRIVER_VERSION_200X,
2049                                    -1};
2050
2051 static int get_version_id(const char *arch)
2052 {
2053         int i;
2054
2055         for (i=0; archi_table[i].long_archi != NULL; i++)
2056         {
2057                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2058                         return (archi_table[i].version);
2059         }
2060
2061         return -1;
2062 }
2063
2064 /****************************************************************
2065  _spoolss_DeletePrinterDriver
2066 ****************************************************************/
2067
2068 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2069                                     struct spoolss_DeletePrinterDriver *r)
2070 {
2071
2072         struct spoolss_DriverInfo8 *info = NULL;
2073         int                             version;
2074         WERROR                          status;
2075         struct dcerpc_binding_handle *b;
2076         TALLOC_CTX *tmp_ctx = NULL;
2077         int i;
2078         bool found;
2079
2080         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2081            and not a printer admin, then fail */
2082
2083         if ( (p->session_info->unix_token->uid != sec_initial_uid())
2084              && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2085                 && !token_contains_name_in_list(
2086                         uidtoname(p->session_info->unix_token->uid),
2087                         p->session_info->info->domain_name,
2088                         NULL,
2089                         p->session_info->security_token,
2090                         lp_printer_admin(-1)) )
2091         {
2092                 return WERR_ACCESS_DENIED;
2093         }
2094
2095         /* check that we have a valid driver name first */
2096
2097         if ((version = get_version_id(r->in.architecture)) == -1) {
2098                 return WERR_INVALID_ENVIRONMENT;
2099         }
2100
2101         tmp_ctx = talloc_new(p->mem_ctx);
2102         if (!tmp_ctx) {
2103                 return WERR_NOMEM;
2104         }
2105
2106         status = winreg_printer_binding_handle(tmp_ctx,
2107                                                get_session_info_system(),
2108                                                p->msg_ctx,
2109                                                &b);
2110         if (!W_ERROR_IS_OK(status)) {
2111                 goto done;
2112         }
2113
2114         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2115                 status = winreg_get_driver(tmp_ctx, b,
2116                                            r->in.architecture, r->in.driver,
2117                                            drv_cversion[i], &info);
2118                 if (!W_ERROR_IS_OK(status)) {
2119                         DEBUG(5, ("skipping del of driver with version %d\n",
2120                                   drv_cversion[i]));
2121                         continue;
2122                 }
2123                 found = true;
2124
2125                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2126                         status = WERR_PRINTER_DRIVER_IN_USE;
2127                         goto done;
2128                 }
2129
2130                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2131                 if (!W_ERROR_IS_OK(status)) {
2132                         DEBUG(0, ("failed del of driver with version %d\n",
2133                                   drv_cversion[i]));
2134                         goto done;
2135                 }
2136         }
2137         if (found == false) {
2138                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2139                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2140         } else {
2141                 status = WERR_OK;
2142         }
2143
2144 done:
2145         talloc_free(tmp_ctx);
2146
2147         return status;
2148 }
2149
2150 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2151                                   struct pipes_struct *p,
2152                                   struct spoolss_DeletePrinterDriverEx *r,
2153                                   struct dcerpc_binding_handle *b,
2154                                   struct spoolss_DriverInfo8 *info)
2155 {
2156         WERROR status;
2157         bool delete_files;
2158
2159         if (printer_driver_in_use(mem_ctx, b, info)) {
2160                 status = WERR_PRINTER_DRIVER_IN_USE;
2161                 goto done;
2162         }
2163
2164         /*
2165          * we have a couple of cases to consider.
2166          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2167          *     then the delete should fail if **any** files overlap with
2168          *     other drivers
2169          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2170          *     non-overlapping files
2171          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2172          *     are set, then do not delete any files
2173          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2174          */
2175
2176         delete_files = r->in.delete_flags
2177                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2178
2179
2180         if (delete_files) {
2181                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2182                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2183                         status = WERR_PRINTER_DRIVER_IN_USE;
2184                         goto done;
2185                 }
2186                 /*
2187                  * printer_driver_files_in_use() has trimmed overlapping files
2188                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2189                  */
2190         }
2191
2192
2193         status = winreg_del_driver(mem_ctx, b, info, info->version);
2194         if (!W_ERROR_IS_OK(status)) {
2195                 goto done;
2196         }
2197
2198         /*
2199          * now delete any associated files if delete_files is
2200          * true. Even if this part failes, we return succes
2201          * because the driver doesn not exist any more
2202          */
2203         if (delete_files) {
2204                 delete_driver_files(get_session_info_system(), info);
2205         }
2206
2207 done:
2208         return status;
2209 }
2210
2211 /****************************************************************
2212  _spoolss_DeletePrinterDriverEx
2213 ****************************************************************/
2214
2215 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2216                                       struct spoolss_DeletePrinterDriverEx *r)
2217 {
2218         struct spoolss_DriverInfo8 *info = NULL;
2219         WERROR                          status;
2220         struct dcerpc_binding_handle *b;
2221         TALLOC_CTX *tmp_ctx = NULL;
2222         int i;
2223         bool found;
2224
2225         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2226            and not a printer admin, then fail */
2227
2228         if ( (p->session_info->unix_token->uid != sec_initial_uid())
2229                 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2230                 && !token_contains_name_in_list(
2231                         uidtoname(p->session_info->unix_token->uid),
2232                         p->session_info->info->domain_name,
2233                         NULL,
2234                         p->session_info->security_token, lp_printer_admin(-1)) )
2235         {
2236                 return WERR_ACCESS_DENIED;
2237         }
2238
2239         /* check that we have a valid driver name first */
2240         if (get_version_id(r->in.architecture) == -1) {
2241                 /* this is what NT returns */
2242                 return WERR_INVALID_ENVIRONMENT;
2243         }
2244
2245         tmp_ctx = talloc_new(p->mem_ctx);
2246         if (!tmp_ctx) {
2247                 return WERR_NOMEM;
2248         }
2249
2250         status = winreg_printer_binding_handle(tmp_ctx,
2251                                                get_session_info_system(),
2252                                                p->msg_ctx,
2253                                                &b);
2254         if (!W_ERROR_IS_OK(status)) {
2255                 goto done;
2256         }
2257
2258         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2259                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2260                  && (drv_cversion[i] != r->in.version)) {
2261                         continue;
2262                 }
2263
2264                 /* check if a driver with this version exists before delete */
2265                 status = winreg_get_driver(tmp_ctx, b,
2266                                            r->in.architecture, r->in.driver,
2267                                            drv_cversion[i], &info);
2268                 if (!W_ERROR_IS_OK(status)) {
2269                         DEBUG(5, ("skipping del of driver with version %d\n",
2270                                   drv_cversion[i]));
2271                         continue;
2272                 }
2273                 found = true;
2274
2275                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2276                 if (!W_ERROR_IS_OK(status)) {
2277                         DEBUG(0, ("failed to delete driver with version %d\n",
2278                                   drv_cversion[i]));
2279                         goto done;
2280                 }
2281         }
2282         if (found == false) {
2283                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2284                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2285         } else {
2286                 status = WERR_OK;
2287         }
2288
2289 done:
2290         talloc_free(tmp_ctx);
2291         return status;
2292 }
2293
2294
2295 /********************************************************************
2296  GetPrinterData on a printer server Handle.
2297 ********************************************************************/
2298
2299 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2300                                             const char *value,
2301                                             enum winreg_Type *type,
2302                                             union spoolss_PrinterData *data)
2303 {
2304         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2305
2306         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2307                 *type = REG_DWORD;
2308                 data->value = 0x00;
2309                 return WERR_OK;
2310         }
2311
2312         if (!strcasecmp_m(value, "BeepEnabled")) {
2313                 *type = REG_DWORD;
2314                 data->value = 0x00;
2315                 return WERR_OK;
2316         }
2317
2318         if (!strcasecmp_m(value, "EventLog")) {
2319                 *type = REG_DWORD;
2320                 /* formally was 0x1b */
2321                 data->value = 0x00;
2322                 return WERR_OK;
2323         }
2324
2325         if (!strcasecmp_m(value, "NetPopup")) {
2326                 *type = REG_DWORD;
2327                 data->value = 0x00;
2328                 return WERR_OK;
2329         }
2330
2331         if (!strcasecmp_m(value, "MajorVersion")) {
2332                 *type = REG_DWORD;
2333
2334                 /* Windows NT 4.0 seems to not allow uploading of drivers
2335                    to a server that reports 0x3 as the MajorVersion.
2336                    need to investigate more how Win2k gets around this .
2337                    -- jerry */
2338
2339                 if (RA_WINNT == get_remote_arch()) {
2340                         data->value = 0x02;
2341                 } else {
2342                         data->value = 0x03;
2343                 }
2344
2345                 return WERR_OK;
2346         }
2347
2348         if (!strcasecmp_m(value, "MinorVersion")) {
2349                 *type = REG_DWORD;
2350                 data->value = 0x00;
2351                 return WERR_OK;
2352         }
2353
2354         /* REG_BINARY
2355          *  uint32_t size        = 0x114
2356          *  uint32_t major       = 5
2357          *  uint32_t minor       = [0|1]
2358          *  uint32_t build       = [2195|2600]
2359          *  extra unicode string = e.g. "Service Pack 3"
2360          */
2361         if (!strcasecmp_m(value, "OSVersion")) {
2362                 DATA_BLOB blob;
2363                 enum ndr_err_code ndr_err;
2364                 struct spoolss_OSVersion os;
2365
2366                 os.major                = 5;    /* Windows 2000 == 5.0 */
2367                 os.minor                = 0;
2368                 os.build                = 2195; /* build */
2369                 os.extra_string         = "";   /* leave extra string empty */
2370
2371                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2372                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2373                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2374                         return WERR_GENERAL_FAILURE;
2375                 }
2376
2377                 *type = REG_BINARY;
2378                 data->binary = blob;
2379
2380                 return WERR_OK;
2381         }
2382
2383
2384         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2385                 *type = REG_SZ;
2386
2387                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2388                 W_ERROR_HAVE_NO_MEMORY(data->string);
2389
2390                 return WERR_OK;
2391         }
2392
2393         if (!strcasecmp_m(value, "Architecture")) {
2394                 *type = REG_SZ;
2395                 data->string = talloc_strdup(mem_ctx,
2396                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2397                 W_ERROR_HAVE_NO_MEMORY(data->string);
2398
2399                 return WERR_OK;
2400         }
2401
2402         if (!strcasecmp_m(value, "DsPresent")) {
2403                 *type = REG_DWORD;
2404
2405                 /* only show the publish check box if we are a
2406                    member of a AD domain */
2407
2408                 if (lp_security() == SEC_ADS) {
2409                         data->value = 0x01;
2410                 } else {
2411                         data->value = 0x00;
2412                 }
2413                 return WERR_OK;
2414         }
2415
2416         if (!strcasecmp_m(value, "DNSMachineName")) {
2417                 const char *hostname = get_mydnsfullname();
2418
2419                 if (!hostname) {
2420                         return WERR_BADFILE;
2421                 }
2422
2423                 *type = REG_SZ;
2424                 data->string = talloc_strdup(mem_ctx, hostname);
2425                 W_ERROR_HAVE_NO_MEMORY(data->string);
2426
2427                 return WERR_OK;
2428         }
2429
2430         *type = REG_NONE;
2431
2432         return WERR_INVALID_PARAM;
2433 }
2434
2435 /****************************************************************
2436  _spoolss_GetPrinterData
2437 ****************************************************************/
2438
2439 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2440                                struct spoolss_GetPrinterData *r)
2441 {
2442         struct spoolss_GetPrinterDataEx r2;
2443
2444         r2.in.handle            = r->in.handle;
2445         r2.in.key_name          = "PrinterDriverData";
2446         r2.in.value_name        = r->in.value_name;
2447         r2.in.offered           = r->in.offered;
2448         r2.out.type             = r->out.type;
2449         r2.out.data             = r->out.data;
2450         r2.out.needed           = r->out.needed;
2451
2452         return _spoolss_GetPrinterDataEx(p, &r2);
2453 }
2454
2455 /*********************************************************
2456  Connect to the client machine.
2457 **********************************************************/
2458
2459 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2460                         struct sockaddr_storage *client_ss, const char *remote_machine)
2461 {
2462         NTSTATUS ret;
2463         struct cli_state *the_cli;
2464         struct sockaddr_storage rm_addr;
2465         char addr[INET6_ADDRSTRLEN];
2466
2467         if ( is_zero_addr(client_ss) ) {
2468                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2469                         remote_machine));
2470                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2471                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2472                         return false;
2473                 }
2474                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2475         } else {
2476                 rm_addr = *client_ss;
2477                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2478                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2479                         addr));
2480         }
2481
2482         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2483                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2484                         addr));
2485                 return false;
2486         }
2487
2488         /* setup the connection */
2489         ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2490                 &rm_addr, 0, "IPC$", "IPC",
2491                 "", /* username */
2492                 "", /* domain */
2493                 "", /* password */
2494                 0, lp_client_signing());
2495
2496         if ( !NT_STATUS_IS_OK( ret ) ) {
2497                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2498                         remote_machine ));
2499                 return false;
2500         }
2501
2502         if ( cli_state_protocol(the_cli) != PROTOCOL_NT1 ) {
2503                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2504                 cli_shutdown(the_cli);
2505                 return false;
2506         }
2507
2508         /*
2509          * Ok - we have an anonymous connection to the IPC$ share.
2510          * Now start the NT Domain stuff :-).
2511          */
2512
2513         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2514         if (!NT_STATUS_IS_OK(ret)) {
2515                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2516                         remote_machine, nt_errstr(ret)));
2517                 cli_shutdown(the_cli);
2518                 return false;
2519         }
2520
2521         return true;
2522 }
2523
2524 /***************************************************************************
2525  Connect to the client.
2526 ****************************************************************************/
2527
2528 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2529                                         uint32_t localprinter,
2530                                         enum winreg_Type type,
2531                                         struct policy_handle *handle,
2532                                         struct notify_back_channel **_chan,
2533                                         struct sockaddr_storage *client_ss,
2534                                         struct messaging_context *msg_ctx)
2535 {
2536         WERROR result;
2537         NTSTATUS status;
2538         struct notify_back_channel *chan;
2539
2540         for (chan = back_channels; chan; chan = chan->next) {
2541                 if (memcmp(&chan->client_address, client_ss,
2542                            sizeof(struct sockaddr_storage)) == 0) {
2543                         break;
2544                 }
2545         }
2546
2547         /*
2548          * If it's the first connection, contact the client
2549          * and connect to the IPC$ share anonymously
2550          */
2551         if (!chan) {
2552                 fstring unix_printer;
2553
2554                 /* the +2 is to strip the leading 2 backslashs */
2555                 fstrcpy(unix_printer, printer + 2);
2556
2557                 chan = talloc_zero(NULL, struct notify_back_channel);
2558                 if (!chan) {
2559                         return false;
2560                 }
2561                 chan->client_address = *client_ss;
2562
2563                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2564                         TALLOC_FREE(chan);
2565                         return false;
2566                 }
2567
2568                 DLIST_ADD(back_channels, chan);
2569
2570                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2571                                    receive_notify2_message_list);
2572         }
2573
2574         if (chan->cli_pipe == NULL ||
2575             chan->cli_pipe->binding_handle == NULL) {
2576                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2577                         "NULL %s for printer %s\n",
2578                         chan->cli_pipe == NULL ?
2579                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2580                         printer));
2581                 return false;
2582         }
2583
2584         /*
2585          * Tell the specific printing tdb we want messages for this printer
2586          * by registering our PID.
2587          */
2588
2589         if (!print_notify_register_pid(snum)) {
2590                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2591                           printer));
2592         }
2593
2594         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2595                                                  talloc_tos(),
2596                                                  printer,
2597                                                  localprinter,
2598                                                  type,
2599                                                  0,
2600                                                  NULL,
2601                                                  handle,
2602                                                  &result);
2603         if (!NT_STATUS_IS_OK(status)) {
2604                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2605                 result = ntstatus_to_werror(status);
2606         } else if (!W_ERROR_IS_OK(result)) {
2607                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2608         }
2609
2610         chan->active_connections++;
2611         *_chan = chan;
2612
2613         return (W_ERROR_IS_OK(result));
2614 }
2615
2616 /****************************************************************
2617  ****************************************************************/
2618
2619 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2620                                                              const struct spoolss_NotifyOption *r)
2621 {
2622         struct spoolss_NotifyOption *option;
2623         uint32_t i,k;
2624
2625         if (!r) {
2626                 return NULL;
2627         }
2628
2629         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2630         if (!option) {
2631                 return NULL;
2632         }
2633
2634         *option = *r;
2635
2636         if (!option->count) {
2637                 return option;
2638         }
2639
2640         option->types = talloc_zero_array(option,
2641                 struct spoolss_NotifyOptionType, option->count);
2642         if (!option->types) {
2643                 talloc_free(option);
2644                 return NULL;
2645         }
2646
2647         for (i=0; i < option->count; i++) {
2648                 option->types[i] = r->types[i];
2649
2650                 if (option->types[i].count) {
2651                         option->types[i].fields = talloc_zero_array(option,
2652                                 union spoolss_Field, option->types[i].count);
2653                         if (!option->types[i].fields) {
2654                                 talloc_free(option);
2655                                 return NULL;
2656                         }
2657                         for (k=0; k<option->types[i].count; k++) {
2658                                 option->types[i].fields[k] =
2659                                         r->types[i].fields[k];
2660                         }
2661                 }
2662         }
2663
2664         return option;
2665 }
2666
2667 /****************************************************************
2668  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2669  *
2670  * before replying OK: status=0 a rpc call is made to the workstation
2671  * asking ReplyOpenPrinter
2672  *
2673  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2674  * called from api_spoolss_rffpcnex
2675 ****************************************************************/
2676
2677 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2678                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2679 {
2680         int snum = -1;
2681         struct spoolss_NotifyOption *option = r->in.notify_options;
2682         struct sockaddr_storage client_ss;
2683         ssize_t client_len;
2684
2685         /* store the notify value in the printer struct */
2686
2687         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2688
2689         if (!Printer) {
2690                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2691                         "Invalid handle (%s:%u:%u).\n",
2692                         OUR_HANDLE(r->in.handle)));
2693                 return WERR_BADFID;
2694         }
2695
2696         Printer->notify.flags           = r->in.flags;
2697         Printer->notify.options         = r->in.options;
2698         Printer->notify.printerlocal    = r->in.printer_local;
2699         Printer->notify.msg_ctx         = p->msg_ctx;
2700
2701         TALLOC_FREE(Printer->notify.option);
2702         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2703
2704         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2705
2706         /* Connect to the client machine and send a ReplyOpenPrinter */
2707
2708         if ( Printer->printer_type == SPLHND_SERVER)
2709                 snum = -1;
2710         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2711                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2712                 return WERR_BADFID;
2713
2714         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2715                   "remote_address is %s\n",
2716                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2717
2718         if (!lp_print_notify_backchannel(snum)) {
2719                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2720                         "backchannel disabled\n"));
2721                 return WERR_SERVER_UNAVAILABLE;
2722         }
2723
2724         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2725                                                   (struct sockaddr *) &client_ss,
2726                                                   sizeof(struct sockaddr_storage));
2727         if (client_len < 0) {
2728                 return WERR_NOMEM;
2729         }
2730
2731         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2732                                         Printer->notify.printerlocal, REG_SZ,
2733                                         &Printer->notify.cli_hnd,
2734                                         &Printer->notify.cli_chan,
2735                                         &client_ss, p->msg_ctx)) {
2736                 return WERR_SERVER_UNAVAILABLE;
2737         }
2738
2739         return WERR_OK;
2740 }
2741
2742 /*******************************************************************
2743  * fill a notify_info_data with the servername
2744  ********************************************************************/
2745
2746 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2747                                        int snum,
2748                                        struct spoolss_Notify *data,
2749                                        print_queue_struct *queue,
2750                                        struct spoolss_PrinterInfo2 *pinfo2,
2751                                        TALLOC_CTX *mem_ctx)
2752 {
2753         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2754 }
2755
2756 /*******************************************************************
2757  * fill a notify_info_data with the printername (not including the servername).
2758  ********************************************************************/
2759
2760 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2761                                         int snum,
2762                                         struct spoolss_Notify *data,
2763                                         print_queue_struct *queue,
2764                                         struct spoolss_PrinterInfo2 *pinfo2,
2765                                         TALLOC_CTX *mem_ctx)
2766 {
2767         /* the notify name should not contain the \\server\ part */
2768         const char *p = strrchr(pinfo2->printername, '\\');
2769
2770         if (!p) {
2771                 p = pinfo2->printername;
2772         } else {
2773                 p++;
2774         }
2775
2776         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2777 }
2778
2779 /*******************************************************************
2780  * fill a notify_info_data with the servicename
2781  ********************************************************************/
2782
2783 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2784                                       int snum,
2785                                       struct spoolss_Notify *data,
2786                                       print_queue_struct *queue,
2787                                       struct spoolss_PrinterInfo2 *pinfo2,
2788                                       TALLOC_CTX *mem_ctx)
2789 {
2790         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2791 }
2792
2793 /*******************************************************************
2794  * fill a notify_info_data with the port name
2795  ********************************************************************/
2796
2797 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2798                                      int snum,
2799                                      struct spoolss_Notify *data,
2800                                      print_queue_struct *queue,
2801                                      struct spoolss_PrinterInfo2 *pinfo2,
2802                                      TALLOC_CTX *mem_ctx)
2803 {
2804         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2805 }
2806
2807 /*******************************************************************
2808  * fill a notify_info_data with the printername
2809  * but it doesn't exist, have to see what to do
2810  ********************************************************************/
2811
2812 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2813                                        int snum,
2814                                        struct spoolss_Notify *data,
2815                                        print_queue_struct *queue,
2816                                        struct spoolss_PrinterInfo2 *pinfo2,
2817                                        TALLOC_CTX *mem_ctx)
2818 {
2819         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2820 }
2821
2822 /*******************************************************************
2823  * fill a notify_info_data with the comment
2824  ********************************************************************/
2825
2826 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2827                                    int snum,
2828                                    struct spoolss_Notify *data,
2829                                    print_queue_struct *queue,
2830                                    struct spoolss_PrinterInfo2 *pinfo2,
2831                                    TALLOC_CTX *mem_ctx)
2832 {
2833         const char *p;
2834
2835         if (*pinfo2->comment == '\0') {
2836                 p = lp_comment(snum);
2837         } else {
2838                 p = pinfo2->comment;
2839         }
2840
2841         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2842 }
2843
2844 /*******************************************************************
2845  * fill a notify_info_data with the comment
2846  * location = "Room 1, floor 2, building 3"
2847  ********************************************************************/
2848
2849 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2850                                     int snum,
2851                                     struct spoolss_Notify *data,
2852                                     print_queue_struct *queue,
2853                                     struct spoolss_PrinterInfo2 *pinfo2,
2854                                     TALLOC_CTX *mem_ctx)
2855 {
2856         const char *loc = pinfo2->location;
2857         NTSTATUS status;
2858
2859         status = printer_list_get_printer(mem_ctx,
2860                                           pinfo2->sharename,
2861                                           NULL,
2862                                           &loc,
2863                                           NULL);
2864         if (NT_STATUS_IS_OK(status)) {
2865                 if (loc == NULL) {
2866                         loc = pinfo2->location;
2867                 }
2868         }
2869
2870         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2871 }
2872
2873 /*******************************************************************
2874  * fill a notify_info_data with the device mode
2875  * jfm:xxxx don't to it for know but that's a real problem !!!
2876  ********************************************************************/
2877
2878 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2879                                    int snum,
2880                                    struct spoolss_Notify *data,
2881                                    print_queue_struct *queue,
2882                                    struct spoolss_PrinterInfo2 *pinfo2,
2883                                    TALLOC_CTX *mem_ctx)
2884 {
2885         /* for a dummy implementation we have to zero the fields */
2886         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2887 }
2888
2889 /*******************************************************************
2890  * fill a notify_info_data with the separator file name
2891  ********************************************************************/
2892
2893 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2894                                    int snum,
2895                                    struct spoolss_Notify *data,
2896                                    print_queue_struct *queue,
2897                                    struct spoolss_PrinterInfo2 *pinfo2,
2898                                    TALLOC_CTX *mem_ctx)
2899 {
2900         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2901 }
2902
2903 /*******************************************************************
2904  * fill a notify_info_data with the print processor
2905  * jfm:xxxx return always winprint to indicate we don't do anything to it
2906  ********************************************************************/
2907
2908 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2909                                            int snum,
2910                                            struct spoolss_Notify *data,
2911                                            print_queue_struct *queue,
2912                                            struct spoolss_PrinterInfo2 *pinfo2,
2913                                            TALLOC_CTX *mem_ctx)
2914 {
2915         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2916 }
2917
2918 /*******************************************************************
2919  * fill a notify_info_data with the print processor options
2920  * jfm:xxxx send an empty string
2921  ********************************************************************/
2922
2923 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2924                                       int snum,
2925                                       struct spoolss_Notify *data,
2926                                       print_queue_struct *queue,
2927                                       struct spoolss_PrinterInfo2 *pinfo2,
2928                                       TALLOC_CTX *mem_ctx)
2929 {
2930         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2931 }
2932
2933 /*******************************************************************
2934  * fill a notify_info_data with the data type
2935  * jfm:xxxx always send RAW as data type
2936  ********************************************************************/
2937
2938 static void spoolss_notify_datatype(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_STRING(data, pinfo2->datatype);
2946 }
2947
2948 /*******************************************************************
2949  * fill a notify_info_data with the security descriptor
2950  * jfm:xxxx send an null pointer to say no security desc
2951  * have to implement security before !
2952  ********************************************************************/
2953
2954 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2955                                          int snum,
2956                                          struct spoolss_Notify *data,
2957                                          print_queue_struct *queue,
2958                                          struct spoolss_PrinterInfo2 *pinfo2,
2959                                          TALLOC_CTX *mem_ctx)
2960 {
2961         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2962 }
2963
2964 /*******************************************************************
2965  * fill a notify_info_data with the attributes
2966  * jfm:xxxx a samba printer is always shared
2967  ********************************************************************/
2968
2969 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2970                                       int snum,
2971                                       struct spoolss_Notify *data,
2972                                       print_queue_struct *queue,
2973                                       struct spoolss_PrinterInfo2 *pinfo2,
2974                                       TALLOC_CTX *mem_ctx)
2975 {
2976         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2977 }
2978
2979 /*******************************************************************
2980  * fill a notify_info_data with the priority
2981  ********************************************************************/
2982
2983 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2984                                     int snum,
2985                                     struct spoolss_Notify *data,
2986                                     print_queue_struct *queue,
2987                                     struct spoolss_PrinterInfo2 *pinfo2,
2988                                     TALLOC_CTX *mem_ctx)
2989 {
2990         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2991 }
2992
2993 /*******************************************************************
2994  * fill a notify_info_data with the default priority
2995  ********************************************************************/
2996
2997 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2998                                             int snum,
2999                                             struct spoolss_Notify *data,
3000                                             print_queue_struct *queue,
3001                                             struct spoolss_PrinterInfo2 *pinfo2,
3002                                             TALLOC_CTX *mem_ctx)
3003 {
3004         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3005 }
3006
3007 /*******************************************************************
3008  * fill a notify_info_data with the start time
3009  ********************************************************************/
3010
3011 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3012                                       int snum,
3013                                       struct spoolss_Notify *data,
3014                                       print_queue_struct *queue,
3015                                       struct spoolss_PrinterInfo2 *pinfo2,
3016                                       TALLOC_CTX *mem_ctx)
3017 {
3018         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3019 }
3020
3021 /*******************************************************************
3022  * fill a notify_info_data with the until time
3023  ********************************************************************/
3024
3025 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3026                                       int snum,
3027                                       struct spoolss_Notify *data,
3028                                       print_queue_struct *queue,
3029                                       struct spoolss_PrinterInfo2 *pinfo2,
3030                                       TALLOC_CTX *mem_ctx)
3031 {
3032         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3033 }
3034
3035 /*******************************************************************
3036  * fill a notify_info_data with the status
3037  ********************************************************************/
3038
3039 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3040                                   int snum,
3041                                   struct spoolss_Notify *data,
3042                                   print_queue_struct *queue,
3043                                   struct spoolss_PrinterInfo2 *pinfo2,
3044                                   TALLOC_CTX *mem_ctx)
3045 {
3046         print_status_struct status;
3047
3048         print_queue_length(msg_ctx, snum, &status);
3049         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3050 }
3051
3052 /*******************************************************************
3053  * fill a notify_info_data with the number of jobs queued
3054  ********************************************************************/
3055
3056 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3057                                  int snum,
3058                                  struct spoolss_Notify *data,
3059                                  print_queue_struct *queue,
3060                                  struct spoolss_PrinterInfo2 *pinfo2,
3061                                  TALLOC_CTX *mem_ctx)
3062 {
3063         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3064                 data, print_queue_length(msg_ctx, snum, NULL));
3065 }
3066
3067 /*******************************************************************
3068  * fill a notify_info_data with the average ppm
3069  ********************************************************************/
3070
3071 static void spoolss_notify_average_ppm(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         /* always respond 8 pages per minutes */
3079         /* a little hard ! */
3080         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3081 }
3082
3083 /*******************************************************************
3084  * fill a notify_info_data with username
3085  ********************************************************************/
3086
3087 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3088                                     int snum,
3089                                     struct spoolss_Notify *data,
3090                                     print_queue_struct *queue,
3091                                     struct spoolss_PrinterInfo2 *pinfo2,
3092                                     TALLOC_CTX *mem_ctx)
3093 {
3094         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3095 }
3096
3097 /*******************************************************************
3098  * fill a notify_info_data with job status
3099  ********************************************************************/
3100
3101 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3102                                       int snum,
3103                                       struct spoolss_Notify *data,
3104                                       print_queue_struct *queue,
3105                                       struct spoolss_PrinterInfo2 *pinfo2,
3106                                       TALLOC_CTX *mem_ctx)
3107 {
3108         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3109 }
3110
3111 /*******************************************************************
3112  * fill a notify_info_data with job name
3113  ********************************************************************/
3114
3115 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3116                                     int snum,
3117                                     struct spoolss_Notify *data,
3118                                     print_queue_struct *queue,
3119                                     struct spoolss_PrinterInfo2 *pinfo2,
3120                                     TALLOC_CTX *mem_ctx)
3121 {
3122         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3123 }
3124
3125 /*******************************************************************
3126  * fill a notify_info_data with job status
3127  ********************************************************************/
3128
3129 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3130                                              int snum,
3131                                              struct spoolss_Notify *data,
3132                                              print_queue_struct *queue,
3133                                              struct spoolss_PrinterInfo2 *pinfo2,
3134                                              TALLOC_CTX *mem_ctx)
3135 {
3136         /*
3137          * Now we're returning job status codes we just return a "" here. JRA.
3138          */
3139
3140         const char *p = "";
3141
3142 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3143         p = "unknown";
3144
3145         switch (queue->status) {
3146         case LPQ_QUEUED:
3147                 p = "Queued";
3148                 break;
3149         case LPQ_PAUSED:
3150                 p = "";    /* NT provides the paused string */
3151                 break;
3152         case LPQ_SPOOLING:
3153                 p = "Spooling";
3154                 break;
3155         case LPQ_PRINTING:
3156                 p = "Printing";
3157                 break;
3158         }
3159 #endif /* NO LONGER NEEDED. */
3160
3161         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3162 }
3163
3164 /*******************************************************************
3165  * fill a notify_info_data with job time
3166  ********************************************************************/
3167
3168 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3169                                     int snum,
3170                                     struct spoolss_Notify *data,
3171                                     print_queue_struct *queue,
3172                                     struct spoolss_PrinterInfo2 *pinfo2,
3173                                     TALLOC_CTX *mem_ctx)
3174 {
3175         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3176 }
3177
3178 /*******************************************************************
3179  * fill a notify_info_data with job size
3180  ********************************************************************/
3181
3182 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3183                                     int snum,
3184                                     struct spoolss_Notify *data,
3185                                     print_queue_struct *queue,
3186                                     struct spoolss_PrinterInfo2 *pinfo2,
3187                                     TALLOC_CTX *mem_ctx)
3188 {
3189         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3190 }
3191
3192 /*******************************************************************
3193  * fill a notify_info_data with page info
3194  ********************************************************************/
3195 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3196                                        int snum,
3197                                 struct spoolss_Notify *data,
3198                                 print_queue_struct *queue,
3199                                 struct spoolss_PrinterInfo2 *pinfo2,
3200                                 TALLOC_CTX *mem_ctx)
3201 {
3202         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3203 }
3204
3205 /*******************************************************************
3206  * fill a notify_info_data with pages printed info.
3207  ********************************************************************/
3208 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3209                                          int snum,
3210                                 struct spoolss_Notify *data,
3211                                 print_queue_struct *queue,
3212                                 struct spoolss_PrinterInfo2 *pinfo2,
3213                                 TALLOC_CTX *mem_ctx)
3214 {
3215         /* Add code when back-end tracks this */
3216         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3217 }
3218
3219 /*******************************************************************
3220  Fill a notify_info_data with job position.
3221  ********************************************************************/
3222
3223 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3224                                         int snum,
3225                                         struct spoolss_Notify *data,
3226                                         print_queue_struct *queue,
3227                                         struct spoolss_PrinterInfo2 *pinfo2,
3228                                         TALLOC_CTX *mem_ctx)
3229 {
3230         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3231 }
3232
3233 /*******************************************************************
3234  Fill a notify_info_data with submitted time.
3235  ********************************************************************/
3236
3237 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3238                                           int snum,
3239                                           struct spoolss_Notify *data,
3240                                           print_queue_struct *queue,
3241                                           struct spoolss_PrinterInfo2 *pinfo2,
3242                                           TALLOC_CTX *mem_ctx)
3243 {
3244         data->data.string.string = NULL;
3245         data->data.string.size = 0;
3246
3247         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3248                                &data->data.string.string,
3249                                &data->data.string.size);
3250
3251 }
3252
3253 struct s_notify_info_data_table
3254 {
3255         enum spoolss_NotifyType type;
3256         uint16_t field;
3257         const char *name;
3258         enum spoolss_NotifyTable variable_type;
3259         void (*fn) (struct messaging_context *msg_ctx,
3260                     int snum, struct spoolss_Notify *data,
3261                     print_queue_struct *queue,
3262                     struct spoolss_PrinterInfo2 *pinfo2,
3263                     TALLOC_CTX *mem_ctx);
3264 };
3265
3266 /* A table describing the various print notification constants and
3267    whether the notification data is a pointer to a variable sized
3268    buffer, a one value uint32_t or a two value uint32_t. */
3269
3270 static const struct s_notify_info_data_table notify_info_data_table[] =
3271 {
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3301 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3302 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3304 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3305 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3306 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3307 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3308 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3309 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3310 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3311 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3312 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3313 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3314 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3315 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3316 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3317 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3318 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3319 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3320 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3321 };
3322
3323 /*******************************************************************
3324  Return the variable_type of info_data structure.
3325 ********************************************************************/
3326
3327 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3328                                                                   uint16_t field)
3329 {
3330         int i=0;
3331
3332         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3333                 if ( (notify_info_data_table[i].type == type) &&
3334                      (notify_info_data_table[i].field == field) ) {
3335                         return notify_info_data_table[i].variable_type;
3336                 }
3337         }
3338
3339         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3340
3341         return (enum spoolss_NotifyTable) 0;
3342 }
3343
3344 /****************************************************************************
3345 ****************************************************************************/
3346
3347 static bool search_notify(enum spoolss_NotifyType type,
3348                           uint16_t field,
3349                           int *value)
3350 {
3351         int i;
3352
3353         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3354                 if (notify_info_data_table[i].type == type &&
3355                     notify_info_data_table[i].field == field &&
3356                     notify_info_data_table[i].fn != NULL) {
3357                         *value = i;
3358                         return true;
3359                 }
3360         }
3361
3362         return false;
3363 }
3364
3365 /****************************************************************************
3366 ****************************************************************************/
3367
3368 static void construct_info_data(struct spoolss_Notify *info_data,
3369                                 enum spoolss_NotifyType type,
3370                                 uint16_t field, int id)
3371 {
3372         info_data->type                 = type;
3373         info_data->field.field          = field;
3374         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3375         info_data->job_id               = id;
3376 }
3377
3378 /*******************************************************************
3379  *
3380  * fill a notify_info struct with info asked
3381  *
3382  ********************************************************************/
3383
3384 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3385                                           struct printer_handle *print_hnd,
3386                                           struct spoolss_NotifyInfo *info,
3387                                           struct spoolss_PrinterInfo2 *pinfo2,
3388                                           int snum,
3389                                           const struct spoolss_NotifyOptionType *option_type,
3390                                           uint32_t id,
3391                                           TALLOC_CTX *mem_ctx)
3392 {
3393         int field_num,j;
3394         enum spoolss_NotifyType type;
3395         uint16_t field;
3396
3397         struct spoolss_Notify *current_data;
3398
3399         type = option_type->type;
3400
3401         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3402                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3403                 option_type->count, lp_servicename(snum)));
3404
3405         for(field_num=0; field_num < option_type->count; field_num++) {
3406                 field = option_type->fields[field_num].field;
3407
3408                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3409
3410                 if (!search_notify(type, field, &j) )
3411                         continue;
3412
3413                 info->notifies = talloc_realloc(info, info->notifies,
3414                                                       struct spoolss_Notify,
3415                                                       info->count + 1);
3416                 if (info->notifies == NULL) {
3417                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3418                         return false;
3419                 }
3420
3421                 current_data = &info->notifies[info->count];
3422
3423                 construct_info_data(current_data, type, field, id);
3424
3425                 DEBUG(10, ("construct_notify_printer_info: "
3426                            "calling [%s]  snum=%d  printername=[%s])\n",
3427                            notify_info_data_table[j].name, snum,
3428                            pinfo2->printername));
3429
3430                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3431                                              NULL, pinfo2, mem_ctx);
3432
3433                 info->count++;
3434         }
3435
3436         return true;
3437 }
3438
3439 /*******************************************************************
3440  *
3441  * fill a notify_info struct with info asked
3442  *
3443  ********************************************************************/
3444
3445 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3446                                        print_queue_struct *queue,
3447                                        struct spoolss_NotifyInfo *info,
3448                                        struct spoolss_PrinterInfo2 *pinfo2,
3449                                        int snum,
3450                                        const struct spoolss_NotifyOptionType *option_type,
3451                                        uint32_t id,
3452                                        TALLOC_CTX *mem_ctx)
3453 {
3454         int field_num,j;
3455         enum spoolss_NotifyType type;
3456         uint16_t field;
3457         struct spoolss_Notify *current_data;
3458
3459         DEBUG(4,("construct_notify_jobs_info\n"));
3460
3461         type = option_type->type;
3462
3463         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3464                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3465                 option_type->count));
3466
3467         for(field_num=0; field_num<option_type->count; field_num++) {
3468                 field = option_type->fields[field_num].field;
3469
3470                 if (!search_notify(type, field, &j) )
3471                         continue;
3472
3473                 info->notifies = talloc_realloc(info, info->notifies,
3474                                                       struct spoolss_Notify,
3475                                                       info->count + 1);
3476                 if (info->notifies == NULL) {
3477                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3478                         return false;
3479                 }
3480
3481                 current_data=&(info->notifies[info->count]);
3482
3483                 construct_info_data(current_data, type, field, id);
3484                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3485                                              queue, pinfo2, mem_ctx);
3486                 info->count++;
3487         }
3488
3489         return true;
3490 }
3491
3492 /*
3493  * JFM: The enumeration is not that simple, it's even non obvious.
3494  *
3495  * let's take an example: I want to monitor the PRINTER SERVER for
3496  * the printer's name and the number of jobs currently queued.
3497  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3498  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3499  *
3500  * I have 3 printers on the back of my server.
3501  *
3502  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3503  * structures.
3504  *   Number     Data                    Id
3505  *      1       printer 1 name          1
3506  *      2       printer 1 cjob          1
3507  *      3       printer 2 name          2
3508  *      4       printer 2 cjob          2
3509  *      5       printer 3 name          3
3510  *      6       printer 3 name          3
3511  *
3512  * that's the print server case, the printer case is even worse.
3513  */
3514
3515 /*******************************************************************
3516  *
3517  * enumerate all printers on the printserver
3518  * fill a notify_info struct with info asked
3519  *
3520  ********************************************************************/
3521
3522 static WERROR printserver_notify_info(struct pipes_struct *p,
3523                                       struct policy_handle *hnd,
3524                                       struct spoolss_NotifyInfo *info,
3525                                       TALLOC_CTX *mem_ctx)
3526 {
3527         int snum;
3528         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3529         int n_services=lp_numservices();
3530         int i;
3531         struct spoolss_NotifyOption *option;
3532         struct spoolss_NotifyOptionType option_type;
3533         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3534         WERROR result;
3535
3536         DEBUG(4,("printserver_notify_info\n"));
3537
3538         if (!Printer)
3539                 return WERR_BADFID;
3540
3541         option = Printer->notify.option;
3542
3543         info->version   = 2;
3544         info->notifies  = NULL;
3545         info->count     = 0;
3546
3547         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3548            sending a ffpcn() request first */
3549
3550         if ( !option )
3551                 return WERR_BADFID;
3552
3553         for (i=0; i<option->count; i++) {
3554                 option_type = option->types[i];
3555
3556                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3557                         continue;
3558
3559                 for (snum = 0; snum < n_services; snum++) {
3560                         if (!lp_browseable(snum) ||
3561                             !lp_snum_ok(snum) ||
3562                             !lp_print_ok(snum)) {
3563                                 continue; /* skip */
3564                         }
3565
3566                         /* Maybe we should use the SYSTEM session_info here... */
3567                         result = winreg_get_printer_internal(mem_ctx,
3568                                                     get_session_info_system(),
3569                                                     p->msg_ctx,
3570                                                     lp_servicename(snum),
3571                                                     &pinfo2);
3572                         if (!W_ERROR_IS_OK(result)) {
3573                                 DEBUG(4, ("printserver_notify_info: "
3574                                           "Failed to get printer [%s]\n",
3575                                           lp_servicename(snum)));
3576                                 continue;
3577                         }
3578
3579
3580                         construct_notify_printer_info(p->msg_ctx,
3581                                                       Printer, info,
3582                                                       pinfo2, snum,
3583                                                       &option_type, snum,
3584                                                       mem_ctx);
3585
3586                         TALLOC_FREE(pinfo2);
3587                 }
3588         }
3589
3590 #if 0
3591         /*
3592          * Debugging information, don't delete.
3593          */
3594
3595         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3596         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3597         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3598
3599         for (i=0; i<info->count; i++) {
3600                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3601                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3602                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3603         }
3604 #endif
3605
3606         return WERR_OK;
3607 }
3608
3609 /*******************************************************************
3610  *
3611  * fill a notify_info struct with info asked
3612  *
3613  ********************************************************************/
3614
3615 static WERROR printer_notify_info(struct pipes_struct *p,
3616                                   struct policy_handle *hnd,
3617                                   struct spoolss_NotifyInfo *info,
3618                                   TALLOC_CTX *mem_ctx)
3619 {
3620         int snum;
3621         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3622         int i;
3623         uint32_t id;
3624         struct spoolss_NotifyOption *option;
3625         struct spoolss_NotifyOptionType option_type;
3626         int count,j;
3627         print_queue_struct *queue=NULL;
3628         print_status_struct status;
3629         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3630         WERROR result;
3631
3632         DEBUG(4,("printer_notify_info\n"));
3633
3634         if (!Printer)
3635                 return WERR_BADFID;
3636
3637         option = Printer->notify.option;
3638         id = 0x0;
3639
3640         info->version   = 2;
3641         info->notifies  = NULL;
3642         info->count     = 0;
3643
3644         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3645            sending a ffpcn() request first */
3646
3647         if ( !option )
3648                 return WERR_BADFID;
3649
3650         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3651                 return WERR_BADFID;
3652         }
3653
3654         /* Maybe we should use the SYSTEM session_info here... */
3655         result = winreg_get_printer_internal(mem_ctx,
3656                                     get_session_info_system(),
3657                                     p->msg_ctx,
3658                                     lp_servicename(snum), &pinfo2);
3659         if (!W_ERROR_IS_OK(result)) {
3660                 return WERR_BADFID;
3661         }
3662
3663         /*
3664          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3665          * correct servername.
3666          */
3667         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3668         if (pinfo2->servername == NULL) {
3669                 return WERR_NOMEM;
3670         }
3671
3672         for (i=0; i<option->count; i++) {
3673                 option_type = option->types[i];
3674
3675                 switch (option_type.type) {
3676                 case PRINTER_NOTIFY_TYPE:
3677                         if (construct_notify_printer_info(p->msg_ctx,
3678                                                           Printer, info,
3679                                                           pinfo2, snum,
3680                                                           &option_type, id,
3681                                                           mem_ctx)) {
3682                                 id--;
3683                         }
3684                         break;
3685
3686                 case JOB_NOTIFY_TYPE:
3687
3688                         count = print_queue_status(p->msg_ctx, snum, &queue,
3689                                                    &status);
3690
3691                         for (j=0; j<count; j++) {
3692                                 construct_notify_jobs_info(p->msg_ctx,
3693                                                            &queue[j], info,
3694                                                            pinfo2, snum,
3695                                                            &option_type,
3696                                                            queue[j].job,
3697                                                            mem_ctx);
3698                         }
3699
3700                         SAFE_FREE(queue);
3701                         break;
3702                 }
3703         }
3704
3705         /*
3706          * Debugging information, don't delete.
3707          */
3708         /*
3709         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3710         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3711         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3712
3713         for (i=0; i<info->count; i++) {
3714                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3715                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3716                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3717         }
3718         */
3719
3720         talloc_free(pinfo2);
3721         return WERR_OK;
3722 }
3723
3724 /****************************************************************
3725  _spoolss_RouterRefreshPrinterChangeNotify
3726 ****************************************************************/
3727
3728 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3729                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3730 {
3731         struct spoolss_NotifyInfo *info;
3732
3733         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3734         WERROR result = WERR_BADFID;
3735
3736         /* we always have a spoolss_NotifyInfo struct */
3737         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3738         if (!info) {
3739                 result = WERR_NOMEM;
3740                 goto done;
3741         }
3742
3743         *r->out.info = info;
3744
3745         if (!Printer) {
3746                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3747                         "Invalid handle (%s:%u:%u).\n",
3748                         OUR_HANDLE(r->in.handle)));
3749                 goto done;
3750         }
3751
3752         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3753
3754         /*
3755          *      We are now using the change value, and
3756          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3757          *      I don't have a global notification system, I'm sending back all the
3758          *      information even when _NOTHING_ has changed.
3759          */
3760
3761         /* We need to keep track of the change value to send back in
3762            RRPCN replies otherwise our updates are ignored. */
3763
3764         Printer->notify.fnpcn = true;
3765
3766         if (Printer->notify.cli_chan != NULL &&
3767             Printer->notify.cli_chan->active_connections > 0) {
3768                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3769                         "Saving change value in request [%x]\n",
3770                         r->in.change_low));
3771                 Printer->notify.change = r->in.change_low;
3772         }
3773
3774         /* just ignore the spoolss_NotifyOption */
3775
3776         switch (Printer->printer_type) {
3777                 case SPLHND_SERVER:
3778                         result = printserver_notify_info(p, r->in.handle,
3779                                                          info, p->mem_ctx);
3780                         break;
3781
3782                 case SPLHND_PRINTER:
3783                         result = printer_notify_info(p, r->in.handle,
3784                                                      info, p->mem_ctx);
3785                         break;
3786         }
3787
3788         Printer->notify.fnpcn = false;
3789
3790 done:
3791         return result;
3792 }
3793
3794 /********************************************************************
3795  ********************************************************************/
3796
3797 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3798                                  const char *servername,
3799                                  const char *printername,
3800                                  const char **printername_p)
3801 {
3802         /* FIXME: add lp_force_printername() */
3803
3804         if (servername == NULL) {
3805                 *printername_p = talloc_strdup(mem_ctx, printername);
3806                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3807                 return WERR_OK;
3808         }
3809
3810         if (servername[0] == '\\' && servername[1] == '\\') {
3811                 servername += 2;
3812         }
3813
3814         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3815         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3816
3817         return WERR_OK;
3818 }
3819
3820 /********************************************************************
3821  ********************************************************************/
3822
3823 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3824                                           const char *printername)
3825 {
3826         if (dm == NULL) {
3827                 return;
3828         }
3829
3830         dm->devicename = talloc_strndup(dm, printername,
3831                                         MIN(strlen(printername), 31));
3832 }
3833
3834 /********************************************************************
3835  * construct_printer_info_0
3836  * fill a printer_info_0 struct
3837  ********************************************************************/
3838
3839 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3840                                       const struct auth_session_info *session_info,
3841                                       struct messaging_context *msg_ctx,
3842                                       struct spoolss_PrinterInfo2 *info2,
3843                                       const char *servername,
3844                                       struct spoolss_PrinterInfo0 *r,
3845                                       int snum)
3846 {
3847         int count;
3848         struct printer_session_counter *session_counter;
3849         struct timeval setuptime;
3850         print_status_struct status;
3851         WERROR result;
3852
3853         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3854         if (!W_ERROR_IS_OK(result)) {
3855                 return result;
3856         }
3857
3858         if (servername) {
3859                 r->servername = talloc_strdup(mem_ctx, servername);
3860                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3861         } else {
3862                 r->servername = NULL;
3863         }
3864
3865         count = print_queue_length(msg_ctx, snum, &status);
3866
3867         /* check if we already have a counter for this printer */
3868         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3869                 if (session_counter->snum == snum)
3870                         break;
3871         }
3872
3873         /* it's the first time, add it to the list */
3874         if (session_counter == NULL) {
3875                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3876                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3877                 session_counter->snum           = snum;
3878                 session_counter->counter        = 0;
3879                 DLIST_ADD(counter_list, session_counter);
3880         }
3881
3882         /* increment it */
3883         session_counter->counter++;
3884
3885         r->cjobs                        = count;
3886         r->total_jobs                   = 0;
3887         r->total_bytes                  = 0;
3888
3889         get_startup_time(&setuptime);
3890         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3891
3892         /* JFM:
3893          * the global_counter should be stored in a TDB as it's common to all the clients
3894          * and should be zeroed on samba startup
3895          */
3896         r->global_counter               = session_counter->counter;
3897         r->total_pages                  = 0;
3898         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3899         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3900         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3901         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3902         r->spooling                     = 0;
3903         r->max_spooling                 = 0;
3904         r->session_counter              = session_counter->counter;
3905         r->num_error_out_of_paper       = 0x0;
3906         r->num_error_not_ready          = 0x0;          /* number of print failure */
3907         r->job_error                    = 0x0;
3908         r->number_of_processors         = 0x1;
3909         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3910         r->high_part_total_bytes        = 0x0;
3911
3912         /* ChangeID in milliseconds*/
3913         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3914                                     info2->sharename, &r->change_id);
3915
3916         r->last_error                   = WERR_OK;
3917         r->status                       = nt_printq_status(status.status);
3918         r->enumerate_network_printers   = 0x0;
3919         r->c_setprinter                 = 0x0;
3920         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3921         r->processor_level              = 0x6;          /* 6  ???*/
3922         r->ref_ic                       = 0;
3923         r->reserved2                    = 0;
3924         r->reserved3                    = 0;
3925
3926         return WERR_OK;
3927 }
3928
3929
3930 /********************************************************************
3931  * construct_printer_info1
3932  * fill a spoolss_PrinterInfo1 struct
3933 ********************************************************************/
3934
3935 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3936                                       const struct spoolss_PrinterInfo2 *info2,
3937                                       uint32_t flags,
3938                                       const char *servername,
3939                                       struct spoolss_PrinterInfo1 *r,
3940                                       int snum)
3941 {
3942         WERROR result;
3943
3944         r->flags                = flags;
3945
3946         if (info2->comment == NULL || info2->comment[0] == '\0') {
3947                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3948         } else {
3949                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3950         }
3951         W_ERROR_HAVE_NO_MEMORY(r->comment);
3952
3953         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3954         if (!W_ERROR_IS_OK(result)) {
3955                 return result;
3956         }
3957
3958         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3959                                                   r->name,
3960                                                   info2->drivername,
3961                                                   r->comment);
3962         W_ERROR_HAVE_NO_MEMORY(r->description);
3963
3964         return WERR_OK;
3965 }
3966
3967 /********************************************************************
3968  * construct_printer_info2
3969  * fill a spoolss_PrinterInfo2 struct
3970 ********************************************************************/
3971
3972 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3973                                       struct messaging_context *msg_ctx,
3974                                       const struct spoolss_PrinterInfo2 *info2,
3975                                       const char *servername,
3976                                       struct spoolss_PrinterInfo2 *r,
3977                                       int snum)
3978 {
3979         int count;
3980         print_status_struct status;
3981         WERROR result;
3982
3983         count = print_queue_length(msg_ctx, snum, &status);
3984
3985         if (servername) {
3986                 r->servername           = talloc_strdup(mem_ctx, servername);
3987                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3988         } else {
3989                 r->servername           = NULL;
3990         }
3991
3992         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3993         if (!W_ERROR_IS_OK(result)) {
3994                 return result;
3995         }
3996
3997         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3998         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3999         r->portname             = talloc_strdup(mem_ctx, info2->portname);
4000         W_ERROR_HAVE_NO_MEMORY(r->portname);
4001         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
4002         W_ERROR_HAVE_NO_MEMORY(r->drivername);
4003
4004         if (info2->comment[0] == '\0') {
4005                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
4006         } else {
4007                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
4008         }
4009         W_ERROR_HAVE_NO_MEMORY(r->comment);
4010
4011         r->location     = talloc_strdup(mem_ctx, info2->location);
4012         if (info2->location[0] == '\0') {
4013                 const char *loc = NULL;
4014                 NTSTATUS nt_status;
4015
4016                 nt_status = printer_list_get_printer(mem_ctx,
4017                                                      info2->sharename,
4018                                                      NULL,
4019                                                      &loc,
4020                                                      NULL);
4021                 if (NT_STATUS_IS_OK(nt_status)) {
4022                         if (loc != NULL) {
4023                                 r->location = talloc_strdup(mem_ctx, loc);
4024                         }
4025                 }
4026         }
4027         W_ERROR_HAVE_NO_MEMORY(r->location);
4028
4029         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4030         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4031         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4032         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4033         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4034         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4035         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4036         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4037
4038         r->attributes           = info2->attributes;
4039
4040         r->priority             = info2->priority;
4041         r->defaultpriority      = info2->defaultpriority;
4042         r->starttime            = info2->starttime;
4043         r->untiltime            = info2->untiltime;
4044         r->status               = nt_printq_status(status.status);
4045         r->cjobs                = count;
4046         r->averageppm           = info2->averageppm;
4047
4048         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4049         if (!r->devmode) {
4050                 DEBUG(8,("Returning NULL Devicemode!\n"));
4051         }
4052
4053         compose_devicemode_devicename(r->devmode, r->printername);
4054
4055         r->secdesc = NULL;
4056
4057         if (info2->secdesc != NULL) {
4058                 /* don't use talloc_steal() here unless you do a deep steal of all
4059                    the SEC_DESC members */
4060
4061                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4062         }
4063
4064         return WERR_OK;
4065 }
4066
4067 /********************************************************************
4068  * construct_printer_info3
4069  * fill a spoolss_PrinterInfo3 struct
4070  ********************************************************************/
4071
4072 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4073                                       const struct spoolss_PrinterInfo2 *info2,
4074                                       const char *servername,
4075                                       struct spoolss_PrinterInfo3 *r,
4076                                       int snum)
4077 {
4078         /* These are the components of the SD we are returning. */
4079
4080         if (info2->secdesc != NULL) {
4081                 /* don't use talloc_steal() here unless you do a deep steal of all
4082                    the SEC_DESC members */
4083
4084                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4085                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4086         }
4087
4088         return WERR_OK;
4089 }
4090
4091 /********************************************************************
4092  * construct_printer_info4
4093  * fill a spoolss_PrinterInfo4 struct
4094  ********************************************************************/
4095
4096 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4097                                       const struct spoolss_PrinterInfo2 *info2,
4098                                       const char *servername,
4099                                       struct spoolss_PrinterInfo4 *r,
4100                                       int snum)
4101 {
4102         WERROR result;
4103
4104         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4105         if (!W_ERROR_IS_OK(result)) {
4106                 return result;
4107         }
4108
4109         if (servername) {
4110                 r->servername   = talloc_strdup(mem_ctx, servername);
4111                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4112         } else {
4113                 r->servername = NULL;
4114         }
4115
4116         r->attributes   = info2->attributes;
4117
4118         return WERR_OK;
4119 }
4120
4121 /********************************************************************
4122  * construct_printer_info5
4123  * fill a spoolss_PrinterInfo5 struct
4124  ********************************************************************/
4125
4126 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4127                                       const struct spoolss_PrinterInfo2 *info2,
4128                                       const char *servername,
4129                                       struct spoolss_PrinterInfo5 *r,
4130                                       int snum)
4131 {
4132         WERROR result;
4133
4134         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4135         if (!W_ERROR_IS_OK(result)) {
4136                 return result;
4137         }
4138
4139         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4140         W_ERROR_HAVE_NO_MEMORY(r->portname);
4141
4142         r->attributes   = info2->attributes;
4143
4144         /* these two are not used by NT+ according to MSDN */
4145         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4146         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4147
4148         return WERR_OK;
4149 }
4150
4151 /********************************************************************
4152  * construct_printer_info_6
4153  * fill a spoolss_PrinterInfo6 struct
4154  ********************************************************************/
4155
4156 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4157                                       struct messaging_context *msg_ctx,
4158                                       const struct spoolss_PrinterInfo2 *info2,
4159                                       const char *servername,
4160                                       struct spoolss_PrinterInfo6 *r,
4161                                       int snum)
4162 {
4163         print_status_struct status;
4164
4165         print_queue_length(msg_ctx, snum, &status);
4166
4167         r->status = nt_printq_status(status.status);
4168
4169         return WERR_OK;
4170 }
4171
4172 /********************************************************************
4173  * construct_printer_info7
4174  * fill a spoolss_PrinterInfo7 struct
4175  ********************************************************************/
4176
4177 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4178                                       struct messaging_context *msg_ctx,
4179                                       const char *servername,
4180                                       struct spoolss_PrinterInfo7 *r,
4181                                       int snum)
4182 {
4183         const struct auth_session_info *session_info = get_session_info_system();
4184         struct GUID guid;
4185
4186         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4187                                  servername,
4188                                  lp_servicename(snum), &guid, NULL)) {
4189                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4190                 r->action = DSPRINT_PUBLISH;
4191         } else {
4192                 r->guid = talloc_strdup(mem_ctx, "");
4193                 r->action = DSPRINT_UNPUBLISH;
4194         }
4195         W_ERROR_HAVE_NO_MEMORY(r->guid);
4196
4197         return WERR_OK;
4198 }
4199
4200 /********************************************************************
4201  * construct_printer_info8
4202  * fill a spoolss_PrinterInfo8 struct
4203  ********************************************************************/
4204
4205 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4206                                       const struct spoolss_PrinterInfo2 *info2,
4207                                       const char *servername,
4208                                       struct spoolss_DeviceModeInfo *r,
4209                                       int snum)
4210 {
4211         WERROR result;
4212         const char *printername;
4213
4214         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4215         if (!W_ERROR_IS_OK(result)) {
4216                 return result;
4217         }
4218
4219         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4220         if (!r->devmode) {
4221                 DEBUG(8,("Returning NULL Devicemode!\n"));
4222         }
4223
4224         compose_devicemode_devicename(r->devmode, printername);
4225
4226         return WERR_OK;
4227 }
4228
4229
4230 /********************************************************************
4231 ********************************************************************/
4232
4233 static bool snum_is_shared_printer(int snum)
4234 {
4235         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4236 }
4237
4238 /********************************************************************
4239  Spoolss_enumprinters.
4240 ********************************************************************/
4241
4242 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4243                                            const struct auth_session_info *session_info,
4244                                            struct messaging_context *msg_ctx,
4245                                            const char *servername,
4246                                            uint32_t level,
4247                                            uint32_t flags,
4248                                            union spoolss_PrinterInfo **info_p,
4249                                            uint32_t *count_p)
4250 {
4251         int snum;
4252         int n_services = lp_numservices();
4253         union spoolss_PrinterInfo *info = NULL;
4254         uint32_t count = 0;
4255         WERROR result = WERR_OK;
4256         struct dcerpc_binding_handle *b = NULL;
4257         TALLOC_CTX *tmp_ctx = NULL;
4258
4259         tmp_ctx = talloc_new(mem_ctx);
4260         if (!tmp_ctx) {
4261                 return WERR_NOMEM;
4262         }
4263
4264         *count_p = 0;
4265         *info_p = NULL;
4266
4267         for (snum = 0; snum < n_services; snum++) {
4268
4269                 const char *printer;
4270                 struct spoolss_PrinterInfo2 *info2;
4271
4272                 if (!snum_is_shared_printer(snum)) {
4273                         continue;
4274                 }
4275
4276                 printer = lp_const_servicename(snum);
4277
4278                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4279                         printer, snum));
4280
4281                 if (b == NULL) {
4282                         result = winreg_printer_binding_handle(tmp_ctx,
4283                                                                session_info,
4284                                                                msg_ctx,
4285                                                                &b);
4286                         if (!W_ERROR_IS_OK(result)) {
4287                                 goto out;
4288                         }
4289                 }
4290
4291                 result = winreg_create_printer(tmp_ctx, b,
4292                                                printer);
4293                 if (!W_ERROR_IS_OK(result)) {
4294                         goto out;
4295                 }
4296
4297                 info = talloc_realloc(tmp_ctx, info,
4298                                             union spoolss_PrinterInfo,
4299                                             count + 1);
4300                 if (!info) {
4301                         result = WERR_NOMEM;
4302                         goto out;
4303                 }
4304
4305                 result = winreg_get_printer(tmp_ctx, b,
4306                                             printer, &info2);
4307                 if (!W_ERROR_IS_OK(result)) {
4308                         goto out;
4309                 }
4310
4311                 switch (level) {
4312                 case 0:
4313                         result = construct_printer_info0(info, session_info,
4314                                                          msg_ctx, info2,
4315                                                          servername,
4316                                                          &info[count].info0, snum);
4317                         break;
4318                 case 1:
4319                         result = construct_printer_info1(info, info2, flags,
4320                                                          servername,
4321                                                          &info[count].info1, snum);
4322                         break;
4323                 case 2:
4324                         result = construct_printer_info2(info, msg_ctx, info2,
4325                                                          servername,
4326                                                          &info[count].info2, snum);
4327                         break;
4328                 case 4:
4329                         result = construct_printer_info4(info, info2,
4330                                                          servername,
4331                                                          &info[count].info4, snum);
4332                         break;
4333                 case 5:
4334                         result = construct_printer_info5(info, info2,
4335                                                          servername,
4336                                                          &info[count].info5, snum);
4337                         break;
4338
4339                 default:
4340                         result = WERR_UNKNOWN_LEVEL;
4341                         goto out;
4342                 }
4343
4344                 if (!W_ERROR_IS_OK(result)) {
4345                         goto out;
4346                 }
4347
4348                 count++;
4349         }
4350
4351 out:
4352         if (W_ERROR_IS_OK(result)) {
4353                 *info_p = talloc_move(mem_ctx, &info);
4354                 *count_p = count;
4355         }
4356
4357         talloc_free(tmp_ctx);
4358
4359         return result;
4360 }
4361
4362 /********************************************************************
4363  * handle enumeration of printers at level 0
4364  ********************************************************************/
4365
4366 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4367                                   const struct auth_session_info *session_info,
4368                                   struct messaging_context *msg_ctx,
4369                                   uint32_t flags,
4370                                   const char *servername,
4371                                   union spoolss_PrinterInfo **info,
4372                                   uint32_t *count)
4373 {
4374         DEBUG(4,("enum_all_printers_info_0\n"));
4375
4376         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4377                                             servername, 0, flags, info, count);
4378 }
4379
4380
4381 /********************************************************************
4382 ********************************************************************/
4383
4384 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4385                                        const struct auth_session_info *session_info,
4386                                        struct messaging_context *msg_ctx,
4387                                        const char *servername,
4388                                        uint32_t flags,
4389                                        union spoolss_PrinterInfo **info,
4390                                        uint32_t *count)
4391 {
4392         DEBUG(4,("enum_all_printers_info_1\n"));
4393
4394         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4395                                             servername, 1, flags, info, count);
4396 }
4397
4398 /********************************************************************
4399  enum_all_printers_info_1_local.
4400 *********************************************************************/
4401
4402 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4403                                              const struct auth_session_info *session_info,
4404                                              struct messaging_context *msg_ctx,
4405                                              const char *servername,
4406                                              union spoolss_PrinterInfo **info,
4407                                              uint32_t *count)
4408 {
4409         DEBUG(4,("enum_all_printers_info_1_local\n"));
4410
4411         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4412                                         servername, PRINTER_ENUM_ICON8, info, count);
4413 }
4414
4415 /********************************************************************
4416  enum_all_printers_info_1_name.
4417 *********************************************************************/
4418
4419 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4420                                             const struct auth_session_info *session_info,
4421                                             struct messaging_context *msg_ctx,
4422                                             const char *servername,
4423                                             union spoolss_PrinterInfo **info,
4424                                             uint32_t *count)
4425 {
4426         const char *s = servername;
4427
4428         DEBUG(4,("enum_all_printers_info_1_name\n"));
4429
4430         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4431                 s = servername + 2;
4432         }
4433
4434         if (!is_myname_or_ipaddr(s)) {
4435                 return WERR_INVALID_NAME;
4436         }
4437
4438         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4439                                         servername, PRINTER_ENUM_ICON8, info, count);
4440 }
4441
4442 /********************************************************************
4443  enum_all_printers_info_1_network.
4444 *********************************************************************/
4445
4446 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4447                                                const struct auth_session_info *session_info,
4448                                                struct messaging_context *msg_ctx,
4449                                                const char *servername,
4450                                                union spoolss_PrinterInfo **info,
4451                                                uint32_t *count)
4452 {
4453         const char *s = servername;
4454
4455         DEBUG(4,("enum_all_printers_info_1_network\n"));
4456
4457         /* If we respond to a enum_printers level 1 on our name with flags
4458            set to PRINTER_ENUM_REMOTE with a list of printers then these
4459            printers incorrectly appear in the APW browse list.
4460            Specifically the printers for the server appear at the workgroup
4461            level where all the other servers in the domain are
4462            listed. Windows responds to this call with a
4463            WERR_CAN_NOT_COMPLETE so we should do the same. */
4464
4465         if (servername[0] == '\\' && servername[1] == '\\') {
4466                  s = servername + 2;
4467         }
4468
4469         if (is_myname_or_ipaddr(s)) {
4470                  return WERR_CAN_NOT_COMPLETE;
4471         }
4472
4473         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4474                                         servername, PRINTER_ENUM_NAME, info, count);
4475 }
4476
4477 /********************************************************************
4478  * api_spoolss_enumprinters
4479  *
4480  * called from api_spoolss_enumprinters (see this to understand)
4481  ********************************************************************/
4482
4483 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4484                                        const struct auth_session_info *session_info,
4485                                        struct messaging_context *msg_ctx,
4486                                        const char *servername,
4487                                        union spoolss_PrinterInfo **info,
4488                                        uint32_t *count)
4489 {
4490         DEBUG(4,("enum_all_printers_info_2\n"));
4491
4492         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4493                                             servername, 2, 0, info, count);
4494 }
4495
4496 /********************************************************************
4497  * handle enumeration of printers at level 1
4498  ********************************************************************/
4499
4500 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4501                                   const struct auth_session_info *session_info,
4502                                   struct messaging_context *msg_ctx,
4503                                   uint32_t flags,
4504                                   const char *servername,
4505                                   union spoolss_PrinterInfo **info,
4506                                   uint32_t *count)
4507 {
4508         /* Not all the flags are equals */
4509
4510         if (flags & PRINTER_ENUM_LOCAL) {
4511                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4512                                                       msg_ctx, servername, info, count);
4513         }
4514
4515         if (flags & PRINTER_ENUM_NAME) {
4516                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4517                                                      msg_ctx, servername, info,
4518                                                      count);
4519         }
4520
4521         if (flags & PRINTER_ENUM_NETWORK) {
4522                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4523                                                         msg_ctx, servername, info,
4524                                                         count);
4525         }
4526
4527         return WERR_OK; /* NT4sp5 does that */
4528 }
4529
4530 /********************************************************************
4531  * handle enumeration of printers at level 2
4532  ********************************************************************/
4533
4534 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4535                                   const struct auth_session_info *session_info,
4536                                   struct messaging_context *msg_ctx,
4537                                   uint32_t flags,
4538                                   const char *servername,
4539                                   union spoolss_PrinterInfo **info,
4540                                   uint32_t *count)
4541 {
4542         if (flags & PRINTER_ENUM_LOCAL) {
4543
4544                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4545                                                 servername,
4546                                                 info, count);
4547         }
4548
4549         if (flags & PRINTER_ENUM_NAME) {
4550                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4551                         return WERR_INVALID_NAME;
4552                 }
4553
4554                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4555                                                 servername,
4556                                                 info, count);
4557         }
4558
4559         if (flags & PRINTER_ENUM_REMOTE) {
4560                 return WERR_UNKNOWN_LEVEL;
4561         }
4562
4563         return WERR_OK;
4564 }
4565
4566 /********************************************************************
4567  * handle enumeration of printers at level 4
4568  ********************************************************************/
4569
4570 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4571                                   const struct auth_session_info *session_info,
4572                                   struct messaging_context *msg_ctx,
4573                                   uint32_t flags,
4574                                   const char *servername,
4575                                   union spoolss_PrinterInfo **info,
4576                                   uint32_t *count)
4577 {
4578         DEBUG(4,("enum_all_printers_info_4\n"));
4579
4580         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4581                                             servername, 4, flags, info, count);
4582 }
4583
4584
4585 /********************************************************************
4586  * handle enumeration of printers at level 5
4587  ********************************************************************/
4588
4589 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4590                                   const struct auth_session_info *session_info,
4591                                   struct messaging_context *msg_ctx,
4592                                   uint32_t flags,
4593                                   const char *servername,
4594                                   union spoolss_PrinterInfo **info,
4595                                   uint32_t *count)
4596 {
4597         DEBUG(4,("enum_all_printers_info_5\n"));
4598
4599         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4600                                             servername, 5, flags, info, count);
4601 }
4602
4603 /****************************************************************
4604  _spoolss_EnumPrinters
4605 ****************************************************************/
4606
4607 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4608                              struct spoolss_EnumPrinters *r)
4609 {
4610         const struct auth_session_info *session_info = get_session_info_system();
4611         WERROR result;
4612
4613         /* that's an [in out] buffer */
4614
4615         if (!r->in.buffer && (r->in.offered != 0)) {
4616                 return WERR_INVALID_PARAM;
4617         }
4618
4619         DEBUG(4,("_spoolss_EnumPrinters\n"));
4620
4621         *r->out.needed = 0;
4622         *r->out.count = 0;
4623         *r->out.info = NULL;
4624
4625         /*
4626          * Level 1:
4627          *          flags==PRINTER_ENUM_NAME
4628          *           if name=="" then enumerates all printers
4629          *           if name!="" then enumerate the printer
4630          *          flags==PRINTER_ENUM_REMOTE
4631          *          name is NULL, enumerate printers
4632          * Level 2: name!="" enumerates printers, name can't be NULL
4633          * Level 3: doesn't exist
4634          * Level 4: does a local registry lookup
4635          * Level 5: same as Level 2
4636          */
4637
4638         if (r->in.server && r->in.server[0] == '\0') {
4639                 r->in.server = NULL;
4640         }
4641
4642         switch (r->in.level) {
4643         case 0:
4644                 result = enumprinters_level0(p->mem_ctx, session_info,
4645                                              p->msg_ctx, r->in.flags,
4646                                              r->in.server,
4647                                              r->out.info, r->out.count);
4648                 break;
4649         case 1:
4650                 result = enumprinters_level1(p->mem_ctx, session_info,
4651                                              p->msg_ctx, r->in.flags,
4652                                              r->in.server,
4653                                              r->out.info, r->out.count);
4654                 break;
4655         case 2:
4656                 result = enumprinters_level2(p->mem_ctx, session_info,
4657                                              p->msg_ctx, r->in.flags,
4658                                              r->in.server,
4659                                              r->out.info, r->out.count);
4660                 break;
4661         case 4:
4662                 result = enumprinters_level4(p->mem_ctx, session_info,
4663                                              p->msg_ctx, r->in.flags,
4664                                              r->in.server,
4665                                              r->out.info, r->out.count);
4666                 break;
4667         case 5:
4668                 result = enumprinters_level5(p->mem_ctx, session_info,
4669                                              p->msg_ctx, r->in.flags,
4670                                              r->in.server,
4671                                              r->out.info, r->out.count);
4672                 break;
4673         default:
4674                 return WERR_UNKNOWN_LEVEL;
4675         }
4676
4677         if (!W_ERROR_IS_OK(result)) {
4678                 return result;
4679         }
4680
4681         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4682                                                      spoolss_EnumPrinters,
4683                                                      *r->out.info, r->in.level,
4684                                                      *r->out.count);
4685         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4686         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4687
4688         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4689 }
4690
4691 /****************************************************************
4692  _spoolss_GetPrinter
4693 ****************************************************************/
4694
4695 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4696                            struct spoolss_GetPrinter *r)
4697 {
4698         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4699         struct spoolss_PrinterInfo2 *info2 = NULL;
4700         WERROR result = WERR_OK;
4701         int snum;
4702
4703         /* that's an [in out] buffer */
4704
4705         if (!r->in.buffer && (r->in.offered != 0)) {
4706                 return WERR_INVALID_PARAM;
4707         }
4708
4709         *r->out.needed = 0;
4710
4711         if (Printer == NULL) {
4712                 return WERR_BADFID;
4713         }
4714
4715         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4716                 return WERR_BADFID;
4717         }
4718
4719         result = winreg_get_printer_internal(p->mem_ctx,
4720                                     get_session_info_system(),
4721                                     p->msg_ctx,
4722                                     lp_const_servicename(snum),
4723                                     &info2);
4724         if (!W_ERROR_IS_OK(result)) {
4725                 goto out;
4726         }
4727
4728         switch (r->in.level) {
4729         case 0:
4730                 result = construct_printer_info0(p->mem_ctx,
4731                                                  get_session_info_system(),
4732                                                  p->msg_ctx,
4733                                                  info2,
4734                                                  Printer->servername,
4735                                                  &r->out.info->info0,
4736                                                  snum);
4737                 break;
4738         case 1:
4739                 result = construct_printer_info1(p->mem_ctx, info2,
4740                                                  PRINTER_ENUM_ICON8,
4741                                                  Printer->servername,
4742                                                  &r->out.info->info1, snum);
4743                 break;
4744         case 2:
4745                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4746                                                  Printer->servername,
4747                                                  &r->out.info->info2, snum);
4748                 break;
4749         case 3:
4750                 result = construct_printer_info3(p->mem_ctx, info2,
4751                                                  Printer->servername,
4752                                                  &r->out.info->info3, snum);
4753                 break;
4754         case 4:
4755                 result = construct_printer_info4(p->mem_ctx, info2,
4756                                                  Printer->servername,
4757                                                  &r->out.info->info4, snum);
4758                 break;
4759         case 5:
4760                 result = construct_printer_info5(p->mem_ctx, info2,
4761                                                  Printer->servername,
4762                                                  &r->out.info->info5, snum);
4763                 break;
4764         case 6:
4765                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4766                                                  Printer->servername,
4767                                                  &r->out.info->info6, snum);
4768                 break;
4769         case 7:
4770                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4771                                                  Printer->servername,
4772                                                  &r->out.info->info7, snum);
4773                 break;
4774         case 8:
4775                 result = construct_printer_info8(p->mem_ctx, info2,
4776                                                  Printer->servername,
4777                                                  &r->out.info->info8, snum);
4778                 break;
4779         default:
4780                 result = WERR_UNKNOWN_LEVEL;
4781                 break;
4782         }
4783         TALLOC_FREE(info2);
4784
4785  out:
4786         if (!W_ERROR_IS_OK(result)) {
4787                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4788                           r->in.level, win_errstr(result)));
4789                 TALLOC_FREE(r->out.info);
4790                 return result;
4791         }
4792
4793         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4794                                                r->out.info, r->in.level);
4795         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4796
4797         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4798 }
4799
4800 /********************************************************************
4801  ********************************************************************/
4802
4803 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4804         do { \
4805                 if (in && strlen(in)) { \
4806                         out = talloc_strdup(mem_ctx, in); \
4807                 } else { \
4808                         out = talloc_strdup(mem_ctx, ""); \
4809                 } \
4810                 W_ERROR_HAVE_NO_MEMORY(out); \
4811         } while (0);
4812
4813 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4814         do { \
4815                 if (in && strlen(in)) { \
4816                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4817                 } else { \
4818                         out = talloc_strdup(mem_ctx, ""); \
4819                 } \
4820                 W_ERROR_HAVE_NO_MEMORY(out); \
4821         } while (0);
4822
4823 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4824                                                   const char **string_array,
4825                                                   const char ***presult,
4826                                                   const char *cservername,
4827                                                   const char *arch,
4828                                                   int version)
4829 {
4830         int i, num_strings = 0;
4831         const char **array = NULL;
4832
4833         if (string_array == NULL) {
4834                 return WERR_INVALID_PARAMETER;
4835         }
4836
4837         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4838                 const char *str = NULL;
4839
4840                 if (cservername == NULL || arch == NULL) {
4841                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4842                 } else {
4843                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4844                 }
4845
4846                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4847                         TALLOC_FREE(array);
4848                         return WERR_NOMEM;
4849                 }
4850         }
4851
4852         if (i > 0) {
4853                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4854                              &array, &num_strings);
4855         }
4856
4857         if (presult) {
4858                 *presult = array;
4859         }
4860
4861         return WERR_OK;
4862 }
4863
4864 /********************************************************************
4865  * fill a spoolss_DriverInfo1 struct
4866  ********************************************************************/
4867
4868 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4869                                         struct spoolss_DriverInfo1 *r,
4870                                         const struct spoolss_DriverInfo8 *driver,
4871                                         const char *servername)
4872 {
4873         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4874         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4875
4876         return WERR_OK;
4877 }
4878
4879 /********************************************************************
4880  * fill a spoolss_DriverInfo2 struct
4881  ********************************************************************/
4882
4883 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4884                                         struct spoolss_DriverInfo2 *r,
4885                                         const struct spoolss_DriverInfo8 *driver,
4886                                         const char *servername)
4887
4888 {
4889         const char *cservername = canon_servername(servername);
4890
4891         r->version              = driver->version;
4892
4893         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4894         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4895         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4896         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4897
4898         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4899                                driver->architecture,
4900                                driver->version,
4901                                driver->driver_path,
4902                                r->driver_path);
4903
4904         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4905                                driver->architecture,
4906                                driver->version,
4907                                driver->data_file,
4908                                r->data_file);
4909
4910         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4911                                driver->architecture,
4912                                driver->version,
4913                                driver->config_file,
4914                                r->config_file);
4915
4916         return WERR_OK;
4917 }
4918
4919 /********************************************************************
4920  * fill a spoolss_DriverInfo3 struct
4921  ********************************************************************/
4922
4923 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4924                                         struct spoolss_DriverInfo3 *r,
4925                                         const struct spoolss_DriverInfo8 *driver,
4926                                         const char *servername)
4927 {
4928         const char *cservername = canon_servername(servername);
4929
4930         r->version              = driver->version;
4931
4932         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4933         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4934         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4935         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4936
4937         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4938                                driver->architecture,
4939                                driver->version,
4940                                driver->driver_path,
4941                                r->driver_path);
4942
4943         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4944                                driver->architecture,
4945                                driver->version,
4946                                driver->data_file,
4947                                r->data_file);
4948
4949         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4950                                driver->architecture,
4951                                driver->version,
4952                                driver->config_file,
4953                                r->config_file);
4954
4955         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4956                                driver->architecture,
4957                                driver->version,
4958                                driver->help_file,
4959                                r->help_file);
4960
4961         FILL_DRIVER_STRING(mem_ctx,
4962                            driver->monitor_name,
4963                            r->monitor_name);
4964
4965         FILL_DRIVER_STRING(mem_ctx,
4966                            driver->default_datatype,
4967                            r->default_datatype);
4968
4969         return string_array_from_driver_info(mem_ctx,
4970                                              driver->dependent_files,
4971                                              &r->dependent_files,
4972                                              cservername,
4973                                              driver->architecture,
4974                                              driver->version);
4975 }
4976
4977 /********************************************************************
4978  * fill a spoolss_DriverInfo4 struct
4979  ********************************************************************/
4980
4981 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4982                                         struct spoolss_DriverInfo4 *r,
4983                                         const struct spoolss_DriverInfo8 *driver,
4984                                         const char *servername)
4985 {
4986         const char *cservername = canon_servername(servername);
4987         WERROR result;
4988
4989         r->version              = driver->version;
4990
4991         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4992         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4993         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4994         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4995
4996         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4997                                driver->architecture,
4998                                driver->version,
4999                                driver->driver_path,
5000                                r->driver_path);
5001
5002         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5003                                driver->architecture,
5004                                driver->version,
5005                                driver->data_file,
5006                                r->data_file);
5007
5008         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5009                                driver->architecture,
5010                                driver->version,
5011                                driver->config_file,
5012                                r->config_file);
5013
5014         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5015                                driver->architecture,
5016                                driver->version,
5017                                driver->help_file,
5018                                r->help_file);
5019
5020         result = string_array_from_driver_info(mem_ctx,
5021                                                driver->dependent_files,
5022                                                &r->dependent_files,
5023                                                cservername,
5024                                                driver->architecture,
5025                                                driver->version);
5026         if (!W_ERROR_IS_OK(result)) {
5027                 return result;
5028         }
5029
5030         FILL_DRIVER_STRING(mem_ctx,
5031                            driver->monitor_name,
5032                            r->monitor_name);
5033
5034         FILL_DRIVER_STRING(mem_ctx,
5035                            driver->default_datatype,
5036                            r->default_datatype);
5037
5038
5039         result = string_array_from_driver_info(mem_ctx,
5040                                                driver->previous_names,
5041                                                &r->previous_names,
5042                                                NULL, NULL, 0);
5043
5044         return result;
5045 }
5046
5047 /********************************************************************
5048  * fill a spoolss_DriverInfo5 struct
5049  ********************************************************************/
5050
5051 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5052                                         struct spoolss_DriverInfo5 *r,
5053                                         const struct spoolss_DriverInfo8 *driver,
5054                                         const char *servername)
5055 {
5056         const char *cservername = canon_servername(servername);
5057
5058         r->version              = driver->version;
5059
5060         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5061         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5062         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5063         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5064
5065         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5066                                driver->architecture,
5067                                driver->version,
5068                                driver->driver_path,
5069                                r->driver_path);
5070
5071         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5072                                driver->architecture,
5073                                driver->version,
5074                                driver->data_file,
5075                                r->data_file);
5076
5077         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5078                                driver->architecture,
5079                                driver->version,
5080                                driver->config_file,
5081                                r->config_file);
5082
5083         r->driver_attributes    = 0;
5084         r->config_version       = 0;
5085         r->driver_version       = 0;
5086
5087         return WERR_OK;
5088 }
5089 /********************************************************************
5090  * fill a spoolss_DriverInfo6 struct
5091  ********************************************************************/
5092
5093 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5094                                         struct spoolss_DriverInfo6 *r,
5095                                         const struct spoolss_DriverInfo8 *driver,
5096                                         const char *servername)
5097 {
5098         const char *cservername = canon_servername(servername);
5099         WERROR result;
5100
5101         r->version              = driver->version;
5102
5103         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5104         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5105         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5106         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5107
5108         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5109                                driver->architecture,
5110                                driver->version,
5111                                driver->driver_path,
5112                                r->driver_path);
5113
5114         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5115                                driver->architecture,
5116                                driver->version,
5117                                driver->data_file,
5118                                r->data_file);
5119
5120         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5121                                driver->architecture,
5122                                driver->version,
5123                                driver->config_file,
5124                                r->config_file);
5125
5126         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5127                                driver->architecture,
5128                                driver->version,
5129                                driver->help_file,
5130                                r->help_file);
5131
5132         FILL_DRIVER_STRING(mem_ctx,
5133                            driver->monitor_name,
5134                            r->monitor_name);
5135
5136         FILL_DRIVER_STRING(mem_ctx,
5137                            driver->default_datatype,
5138                            r->default_datatype);
5139
5140         result = string_array_from_driver_info(mem_ctx,
5141                                                driver->dependent_files,
5142                                                &r->dependent_files,
5143                                                cservername,
5144                                                driver->architecture,
5145                                                driver->version);
5146         if (!W_ERROR_IS_OK(result)) {
5147                 return result;
5148         }
5149
5150         result = string_array_from_driver_info(mem_ctx,
5151                                                driver->previous_names,
5152                                                &r->previous_names,
5153                                                NULL, NULL, 0);
5154         if (!W_ERROR_IS_OK(result)) {
5155                 return result;
5156         }
5157
5158         r->driver_date          = driver->driver_date;
5159         r->driver_version       = driver->driver_version;
5160
5161         FILL_DRIVER_STRING(mem_ctx,
5162                            driver->manufacturer_name,
5163                            r->manufacturer_name);
5164         FILL_DRIVER_STRING(mem_ctx,
5165                            driver->manufacturer_url,
5166                            r->manufacturer_url);
5167         FILL_DRIVER_STRING(mem_ctx,
5168                            driver->hardware_id,
5169                            r->hardware_id);
5170         FILL_DRIVER_STRING(mem_ctx,
5171                            driver->provider,
5172                            r->provider);
5173
5174         return WERR_OK;
5175 }
5176
5177 /********************************************************************
5178  * fill a spoolss_DriverInfo8 struct
5179  ********************************************************************/
5180
5181 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5182                                         struct spoolss_DriverInfo8 *r,
5183                                         const struct spoolss_DriverInfo8 *driver,
5184                                         const char *servername)
5185 {
5186         const char *cservername = canon_servername(servername);
5187         WERROR result;
5188
5189         r->version              = driver->version;
5190
5191         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5192         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5193         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5194         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5195
5196         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5197                                driver->architecture,
5198                                driver->version,
5199                                driver->driver_path,
5200                                r->driver_path);
5201
5202         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5203                                driver->architecture,
5204                                driver->version,
5205                                driver->data_file,
5206                                r->data_file);
5207
5208         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5209                                driver->architecture,
5210                                driver->version,
5211                                driver->config_file,
5212                                r->config_file);
5213
5214         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5215                                driver->architecture,
5216                                driver->version,
5217                                driver->help_file,
5218                                r->help_file);
5219
5220         FILL_DRIVER_STRING(mem_ctx,
5221                            driver->monitor_name,
5222                            r->monitor_name);
5223
5224         FILL_DRIVER_STRING(mem_ctx,
5225                            driver->default_datatype,
5226                            r->default_datatype);
5227
5228         result = string_array_from_driver_info(mem_ctx,
5229                                                driver->dependent_files,
5230                                                &r->dependent_files,
5231                                                cservername,
5232                                                driver->architecture,
5233                                                driver->version);
5234         if (!W_ERROR_IS_OK(result)) {
5235                 return result;
5236         }
5237
5238         result = string_array_from_driver_info(mem_ctx,
5239                                                driver->previous_names,
5240                                                &r->previous_names,
5241                                                NULL, NULL, 0);
5242         if (!W_ERROR_IS_OK(result)) {
5243                 return result;
5244         }
5245
5246         r->driver_date          = driver->driver_date;
5247         r->driver_version       = driver->driver_version;
5248
5249         FILL_DRIVER_STRING(mem_ctx,
5250                            driver->manufacturer_name,
5251                            r->manufacturer_name);
5252         FILL_DRIVER_STRING(mem_ctx,
5253                            driver->manufacturer_url,
5254                            r->manufacturer_url);
5255         FILL_DRIVER_STRING(mem_ctx,
5256                            driver->hardware_id,
5257                            r->hardware_id);
5258         FILL_DRIVER_STRING(mem_ctx,
5259                            driver->provider,
5260                            r->provider);
5261
5262         FILL_DRIVER_STRING(mem_ctx,
5263                            driver->print_processor,
5264                            r->print_processor);
5265         FILL_DRIVER_STRING(mem_ctx,
5266                            driver->vendor_setup,
5267                            r->vendor_setup);
5268
5269         result = string_array_from_driver_info(mem_ctx,
5270                                                driver->color_profiles,
5271                                                &r->color_profiles,
5272                                                NULL, NULL, 0);
5273         if (!W_ERROR_IS_OK(result)) {
5274                 return result;
5275         }
5276
5277         FILL_DRIVER_STRING(mem_ctx,
5278                            driver->inf_path,
5279                            r->inf_path);
5280
5281         r->printer_driver_attributes    = driver->printer_driver_attributes;
5282
5283         result = string_array_from_driver_info(mem_ctx,
5284                                                driver->core_driver_dependencies,
5285                                                &r->core_driver_dependencies,
5286                                                NULL, NULL, 0);
5287         if (!W_ERROR_IS_OK(result)) {
5288                 return result;
5289         }
5290
5291         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5292         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5293
5294         return WERR_OK;
5295 }
5296
5297 #if 0 /* disabled until marshalling issues are resolved - gd */
5298 /********************************************************************
5299  ********************************************************************/
5300
5301 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5302                                           struct spoolss_DriverFileInfo *r,
5303                                           const char *cservername,
5304                                           const char *file_name,
5305                                           enum spoolss_DriverFileType file_type,
5306                                           uint32_t file_version)
5307 {
5308         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5309                                           cservername, file_name);
5310         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5311         r->file_type    = file_type;
5312         r->file_version = file_version;
5313
5314         return WERR_OK;
5315 }
5316
5317 /********************************************************************
5318  ********************************************************************/
5319
5320 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5321                                                  const struct spoolss_DriverInfo8 *driver,
5322                                                  const char *cservername,
5323                                                  struct spoolss_DriverFileInfo **info_p,
5324                                                  uint32_t *count_p)
5325 {
5326         struct spoolss_DriverFileInfo *info = NULL;
5327         uint32_t count = 0;
5328         WERROR result;
5329         uint32_t i;
5330
5331         *info_p = NULL;
5332         *count_p = 0;
5333
5334         if (strlen(driver->driver_path)) {
5335                 info = talloc_realloc(mem_ctx, info,
5336                                             struct spoolss_DriverFileInfo,
5337                                             count + 1);
5338                 W_ERROR_HAVE_NO_MEMORY(info);
5339                 result = fill_spoolss_DriverFileInfo(info,
5340                                                      &info[count],
5341                                                      cservername,
5342                                                      driver->driver_path,
5343                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5344                                                      0);
5345                 W_ERROR_NOT_OK_RETURN(result);
5346                 count++;
5347         }
5348
5349         if (strlen(driver->config_file)) {
5350                 info = talloc_realloc(mem_ctx, info,
5351                                             struct spoolss_DriverFileInfo,
5352                                             count + 1);
5353                 W_ERROR_HAVE_NO_MEMORY(info);
5354                 result = fill_spoolss_DriverFileInfo(info,
5355                                                      &info[count],
5356                                                      cservername,
5357                                                      driver->config_file,
5358                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5359                                                      0);
5360                 W_ERROR_NOT_OK_RETURN(result);
5361                 count++;
5362         }
5363
5364         if (strlen(driver->data_file)) {
5365                 info = talloc_realloc(mem_ctx, info,
5366                                             struct spoolss_DriverFileInfo,
5367                                             count + 1);
5368                 W_ERROR_HAVE_NO_MEMORY(info);
5369                 result = fill_spoolss_DriverFileInfo(info,
5370                                                      &info[count],
5371                                                      cservername,
5372                                                      driver->data_file,
5373                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5374                                                      0);
5375                 W_ERROR_NOT_OK_RETURN(result);
5376                 count++;
5377         }
5378
5379         if (strlen(driver->help_file)) {
5380                 info = talloc_realloc(mem_ctx, info,
5381                                             struct spoolss_DriverFileInfo,
5382                                             count + 1);
5383                 W_ERROR_HAVE_NO_MEMORY(info);
5384                 result = fill_spoolss_DriverFileInfo(info,
5385                                                      &info[count],
5386                                                      cservername,
5387                                                      driver->help_file,
5388                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5389                                                      0);
5390                 W_ERROR_NOT_OK_RETURN(result);
5391                 count++;
5392         }
5393
5394         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5395                 info = talloc_realloc(mem_ctx, info,
5396                                             struct spoolss_DriverFileInfo,
5397                                             count + 1);
5398                 W_ERROR_HAVE_NO_MEMORY(info);
5399                 result = fill_spoolss_DriverFileInfo(info,
5400                                                      &info[count],
5401                                                      cservername,
5402                                                      driver->dependent_files[i],
5403                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5404                                                      0);
5405                 W_ERROR_NOT_OK_RETURN(result);
5406                 count++;
5407         }
5408
5409         *info_p = info;
5410         *count_p = count;
5411
5412         return WERR_OK;
5413 }
5414
5415 /********************************************************************
5416  * fill a spoolss_DriverInfo101 struct
5417  ********************************************************************/
5418
5419 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5420                                           struct spoolss_DriverInfo101 *r,
5421                                           const struct spoolss_DriverInfo8 *driver,
5422                                           const char *servername)
5423 {
5424         const char *cservername = canon_servername(servername);
5425         WERROR result;
5426
5427         r->version              = driver->version;
5428
5429         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5430         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5431         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5432         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5433
5434         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5435                                                     cservername,
5436                                                     &r->file_info,
5437                                                     &r->file_count);
5438         if (!W_ERROR_IS_OK(result)) {
5439                 return result;
5440         }
5441
5442         FILL_DRIVER_STRING(mem_ctx,
5443                            driver->monitor_name,
5444                            r->monitor_name);
5445
5446         FILL_DRIVER_STRING(mem_ctx,
5447                            driver->default_datatype,
5448                            r->default_datatype);
5449
5450         result = string_array_from_driver_info(mem_ctx,
5451                                                driver->previous_names,
5452                                                &r->previous_names,
5453                                                NULL, NULL, 0);
5454         if (!W_ERROR_IS_OK(result)) {
5455                 return result;
5456         }
5457
5458         r->driver_date          = driver->driver_date;
5459         r->driver_version       = driver->driver_version;
5460
5461         FILL_DRIVER_STRING(mem_ctx,
5462                            driver->manufacturer_name,
5463                            r->manufacturer_name);
5464         FILL_DRIVER_STRING(mem_ctx,
5465                            driver->manufacturer_url,
5466                            r->manufacturer_url);
5467         FILL_DRIVER_STRING(mem_ctx,
5468                            driver->hardware_id,
5469                            r->hardware_id);
5470         FILL_DRIVER_STRING(mem_ctx,
5471                            driver->provider,
5472                            r->provider);
5473
5474         return WERR_OK;
5475 }
5476 #endif
5477 /********************************************************************
5478  ********************************************************************/
5479
5480 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5481                                                   const struct auth_session_info *session_info,
5482                                                   struct messaging_context *msg_ctx,
5483                                                   uint32_t level,
5484                                                   union spoolss_DriverInfo *r,
5485                                                   int snum,
5486                                                   const char *servername,
5487                                                   const char *architecture,
5488                                                   uint32_t version)
5489 {
5490         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5491         struct spoolss_DriverInfo8 *driver;
5492         WERROR result;
5493         struct dcerpc_binding_handle *b;
5494         TALLOC_CTX *tmp_ctx = NULL;
5495
5496         if (level == 101) {
5497                 return WERR_UNKNOWN_LEVEL;
5498         }
5499
5500         tmp_ctx = talloc_new(mem_ctx);
5501         if (!tmp_ctx) {
5502                 return WERR_NOMEM;
5503         }
5504
5505         result = winreg_printer_binding_handle(tmp_ctx,
5506                                                session_info,
5507                                                msg_ctx,
5508                                                &b);
5509         if (!W_ERROR_IS_OK(result)) {
5510                 goto done;
5511         }
5512
5513         result = winreg_get_printer(tmp_ctx, b,
5514                                     lp_const_servicename(snum),
5515                                     &pinfo2);
5516
5517         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5518                 win_errstr(result)));
5519
5520         if (!W_ERROR_IS_OK(result)) {
5521                 result = WERR_INVALID_PRINTER_NAME;
5522                 goto done;
5523         }
5524
5525         result = winreg_get_driver(tmp_ctx, b,
5526                                    architecture,
5527                                    pinfo2->drivername, version, &driver);
5528
5529         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5530                 win_errstr(result)));
5531
5532         if (!W_ERROR_IS_OK(result)) {
5533                 /*
5534                  * Is this a W2k client ?
5535                  */
5536
5537                 if (version < 3) {
5538                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5539                         goto done;
5540                 }
5541
5542                 /* Yes - try again with a WinNT driver. */
5543                 version = 2;
5544                 result = winreg_get_driver(tmp_ctx, b,
5545                                            architecture,
5546                                            pinfo2->drivername,
5547                                            version, &driver);
5548                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5549                         win_errstr(result)));
5550                 if (!W_ERROR_IS_OK(result)) {
5551                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5552                         goto done;
5553                 }
5554         }
5555
5556         /* these are allocated on mem_ctx and not tmp_ctx because they are
5557          * the 'return value' and need to utlive this call */
5558         switch (level) {
5559         case 1:
5560                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5561                 break;
5562         case 2:
5563                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5564                 break;
5565         case 3:
5566                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5567                 break;
5568         case 4:
5569                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5570                 break;
5571         case 5:
5572                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5573                 break;
5574         case 6:
5575                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5576                 break;
5577         case 8:
5578                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5579                 break;
5580 #if 0 /* disabled until marshalling issues are resolved - gd */
5581         case 101:
5582                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5583                 break;
5584 #endif
5585         default:
5586                 result = WERR_UNKNOWN_LEVEL;
5587                 break;
5588         }
5589
5590 done:
5591         talloc_free(tmp_ctx);
5592         return result;
5593 }
5594
5595 /****************************************************************
5596  _spoolss_GetPrinterDriver2
5597 ****************************************************************/
5598
5599 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5600                                   struct spoolss_GetPrinterDriver2 *r)
5601 {
5602         struct printer_handle *printer;
5603         WERROR result;
5604
5605         int snum;
5606
5607         /* that's an [in out] buffer */
5608
5609         if (!r->in.buffer && (r->in.offered != 0)) {
5610                 return WERR_INVALID_PARAM;
5611         }
5612
5613         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5614
5615         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5616                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5617                 return WERR_INVALID_PRINTER_NAME;
5618         }
5619
5620         *r->out.needed = 0;
5621         *r->out.server_major_version = 0;
5622         *r->out.server_minor_version = 0;
5623
5624         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5625                 return WERR_BADFID;
5626         }
5627
5628         result = construct_printer_driver_info_level(p->mem_ctx,
5629                                                      get_session_info_system(),
5630                                                      p->msg_ctx,
5631                                                      r->in.level, r->out.info,
5632                                                      snum, printer->servername,
5633                                                      r->in.architecture,
5634                                                      r->in.client_major_version);
5635         if (!W_ERROR_IS_OK(result)) {
5636                 TALLOC_FREE(r->out.info);
5637                 return result;
5638         }
5639
5640         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5641                                                r->out.info, r->in.level);
5642         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5643
5644         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5645 }
5646
5647
5648 /****************************************************************
5649  _spoolss_StartPagePrinter
5650 ****************************************************************/
5651
5652 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5653                                  struct spoolss_StartPagePrinter *r)
5654 {
5655         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5656
5657         if (!Printer) {
5658                 DEBUG(3,("_spoolss_StartPagePrinter: "
5659                         "Error in startpageprinter printer handle\n"));
5660                 return WERR_BADFID;
5661         }
5662
5663         Printer->page_started = true;
5664         return WERR_OK;
5665 }
5666
5667 /****************************************************************
5668  _spoolss_EndPagePrinter
5669 ****************************************************************/
5670
5671 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5672                                struct spoolss_EndPagePrinter *r)
5673 {
5674         int snum;
5675
5676         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5677
5678         if (!Printer) {
5679                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5680                         OUR_HANDLE(r->in.handle)));
5681                 return WERR_BADFID;
5682         }
5683
5684         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5685                 return WERR_BADFID;
5686
5687         Printer->page_started = false;
5688         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5689
5690         return WERR_OK;
5691 }
5692
5693 /****************************************************************
5694  _spoolss_StartDocPrinter
5695 ****************************************************************/
5696
5697 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5698                                 struct spoolss_StartDocPrinter *r)
5699 {
5700         struct spoolss_DocumentInfo1 *info_1;
5701         int snum;
5702         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5703         WERROR werr;
5704         char *rhost;
5705         int rc;
5706
5707         if (!Printer) {
5708                 DEBUG(2,("_spoolss_StartDocPrinter: "
5709                         "Invalid handle (%s:%u:%u)\n",
5710                         OUR_HANDLE(r->in.handle)));
5711                 return WERR_BADFID;
5712         }
5713
5714         if (Printer->jobid) {
5715                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5716                           "StartDocPrinter called twice! "
5717                           "(existing jobid = %d)\n", Printer->jobid));
5718                 return WERR_INVALID_HANDLE;
5719         }
5720
5721         if (r->in.level != 1) {
5722                 return WERR_UNKNOWN_LEVEL;
5723         }
5724
5725         info_1 = r->in.info.info1;
5726
5727         /*
5728          * a nice thing with NT is it doesn't listen to what you tell it.
5729          * when asked to send _only_ RAW datas, it tries to send datas
5730          * in EMF format.
5731          *
5732          * So I add checks like in NT Server ...
5733          */
5734
5735         if (info_1->datatype) {
5736                 if (strcmp(info_1->datatype, "RAW") != 0) {
5737                         *r->out.job_id = 0;
5738                         return WERR_INVALID_DATATYPE;
5739                 }
5740         }
5741
5742         /* get the share number of the printer */
5743         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5744                 return WERR_BADFID;
5745         }
5746
5747         rc = get_remote_hostname(p->remote_address,
5748                                  &rhost,
5749                                  p->mem_ctx);
5750         if (rc < 0) {
5751                 return WERR_NOMEM;
5752         }
5753         if (strequal(rhost,"UNKNOWN")) {
5754                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5755                                                          p->mem_ctx);
5756                 if (rhost == NULL) {
5757                         return WERR_NOMEM;
5758                 }
5759         }
5760
5761         werr = print_job_start(p->session_info,
5762                                p->msg_ctx,
5763                                rhost,
5764                                snum,
5765                                info_1->document_name,
5766                                info_1->output_file,
5767                                Printer->devmode,
5768                                &Printer->jobid);
5769
5770         /* An error occured in print_job_start() so return an appropriate
5771            NT error code. */
5772
5773         if (!W_ERROR_IS_OK(werr)) {
5774                 return werr;
5775         }
5776
5777         Printer->document_started = true;
5778         *r->out.job_id = Printer->jobid;
5779
5780         return WERR_OK;
5781 }
5782
5783 /****************************************************************
5784  _spoolss_EndDocPrinter
5785 ****************************************************************/
5786
5787 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5788                               struct spoolss_EndDocPrinter *r)
5789 {
5790         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5791         NTSTATUS status;
5792         int snum;
5793
5794         if (!Printer) {
5795                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5796                         OUR_HANDLE(r->in.handle)));
5797                 return WERR_BADFID;
5798         }
5799
5800         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5801                 return WERR_BADFID;
5802         }
5803
5804         Printer->document_started = false;
5805         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5806         if (!NT_STATUS_IS_OK(status)) {
5807                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5808                           "print_job_end failed [%s]\n",
5809                           nt_errstr(status)));
5810         }
5811
5812         Printer->jobid = 0;
5813         return ntstatus_to_werror(status);
5814 }
5815
5816 /****************************************************************
5817  _spoolss_WritePrinter
5818 ****************************************************************/
5819
5820 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5821                              struct spoolss_WritePrinter *r)
5822 {
5823         ssize_t buffer_written;
5824         int snum;
5825         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5826
5827         if (!Printer) {
5828                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5829                         OUR_HANDLE(r->in.handle)));
5830                 *r->out.num_written = r->in._data_size;
5831                 return WERR_BADFID;
5832         }
5833
5834         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5835                 return WERR_BADFID;
5836
5837         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5838         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5839                                                    snum, Printer->jobid,
5840                                                    (const char *)r->in.data.data,
5841                                                    (size_t)r->in._data_size);
5842         if (buffer_written == (ssize_t)-1) {
5843                 *r->out.num_written = 0;
5844                 if (errno == ENOSPC)
5845                         return WERR_NO_SPOOL_SPACE;
5846                 else
5847                         return WERR_ACCESS_DENIED;
5848         }
5849
5850         *r->out.num_written = r->in._data_size;
5851
5852         return WERR_OK;
5853 }
5854
5855 /********************************************************************
5856  * api_spoolss_getprinter
5857  * called from the spoolss dispatcher
5858  *
5859  ********************************************************************/
5860
5861 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5862                               struct pipes_struct *p)
5863 {
5864         const struct auth_session_info *session_info = p->session_info;
5865         int snum;
5866         WERROR errcode = WERR_BADFUNC;
5867         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5868
5869         if (!Printer) {
5870                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5871                         OUR_HANDLE(handle)));
5872                 return WERR_BADFID;
5873         }
5874
5875         if (!get_printer_snum(p, handle, &snum, NULL))
5876                 return WERR_BADFID;
5877
5878         switch (command) {
5879         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5880                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5881                 break;
5882         case SPOOLSS_PRINTER_CONTROL_RESUME:
5883         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5884                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5885                 break;
5886         case SPOOLSS_PRINTER_CONTROL_PURGE:
5887                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5888                 break;
5889         default:
5890                 return WERR_UNKNOWN_LEVEL;
5891         }
5892
5893         return errcode;
5894 }
5895
5896
5897 /****************************************************************
5898  _spoolss_AbortPrinter
5899  * From MSDN: "Deletes printer's spool file if printer is configured
5900  * for spooling"
5901 ****************************************************************/
5902
5903 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5904                              struct spoolss_AbortPrinter *r)
5905 {
5906         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5907         int             snum;
5908         WERROR          errcode = WERR_OK;
5909
5910         if (!Printer) {
5911                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5912                         OUR_HANDLE(r->in.handle)));
5913                 return WERR_BADFID;
5914         }
5915
5916         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5917                 return WERR_BADFID;
5918
5919         if (!Printer->document_started) {
5920                 return WERR_SPL_NO_STARTDOC;
5921         }
5922
5923         errcode = print_job_delete(p->session_info,
5924                                    p->msg_ctx,
5925                                    snum,
5926                                    Printer->jobid);
5927
5928         return errcode;
5929 }
5930
5931 /********************************************************************
5932  * called by spoolss_api_setprinter
5933  * when updating a printer description
5934  ********************************************************************/
5935
5936 static WERROR update_printer_sec(struct policy_handle *handle,
5937                                  struct pipes_struct *p,
5938                                  struct sec_desc_buf *secdesc_ctr)
5939 {
5940         struct spoolss_security_descriptor *new_secdesc = NULL;
5941         struct spoolss_security_descriptor *old_secdesc = NULL;
5942         const char *printer;
5943         WERROR result;
5944         int snum;
5945         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5946         struct dcerpc_binding_handle *b;
5947         TALLOC_CTX *tmp_ctx = NULL;
5948
5949         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5950                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5951                          OUR_HANDLE(handle)));
5952
5953                 result = WERR_BADFID;
5954                 goto done;
5955         }
5956
5957         if (secdesc_ctr == NULL) {
5958                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5959                 result = WERR_INVALID_PARAM;
5960                 goto done;
5961         }
5962         printer = lp_const_servicename(snum);
5963
5964         /* Check the user has permissions to change the security
5965            descriptor.  By experimentation with two NT machines, the user
5966            requires Full Access to the printer to change security
5967            information. */
5968
5969         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5970                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5971                 result = WERR_ACCESS_DENIED;
5972                 goto done;
5973         }
5974
5975         tmp_ctx = talloc_new(p->mem_ctx);
5976         if (!tmp_ctx) {
5977                 return WERR_NOMEM;
5978         }
5979
5980         result = winreg_printer_binding_handle(tmp_ctx,
5981                                                get_session_info_system(),
5982                                                p->msg_ctx,
5983                                                &b);
5984         if (!W_ERROR_IS_OK(result)) {
5985                 goto done;
5986         }
5987
5988         /* NT seems to like setting the security descriptor even though
5989            nothing may have actually changed. */
5990         result = winreg_get_printer_secdesc(tmp_ctx, b,
5991                                             printer,
5992                                             &old_secdesc);
5993         if (!W_ERROR_IS_OK(result)) {
5994                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
5995                 result = WERR_BADFID;
5996                 goto done;
5997         }
5998
5999         if (DEBUGLEVEL >= 10) {
6000                 struct security_acl *the_acl;
6001                 int i;
6002
6003                 the_acl = old_secdesc->dacl;
6004                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6005                            printer, the_acl->num_aces));
6006
6007                 for (i = 0; i < the_acl->num_aces; i++) {
6008                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6009                                            &the_acl->aces[i].trustee),
6010                                   the_acl->aces[i].access_mask));
6011                 }
6012
6013                 the_acl = secdesc_ctr->sd->dacl;
6014
6015                 if (the_acl) {
6016                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6017                                    printer, the_acl->num_aces));
6018
6019                         for (i = 0; i < the_acl->num_aces; i++) {
6020                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6021                                                    &the_acl->aces[i].trustee),
6022                                            the_acl->aces[i].access_mask));
6023                         }
6024                 } else {
6025                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6026                 }
6027         }
6028
6029         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6030         if (new_secdesc == NULL) {
6031                 result = WERR_NOMEM;
6032                 goto done;
6033         }
6034
6035         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6036                 result = WERR_OK;
6037                 goto done;
6038         }
6039
6040         result = winreg_set_printer_secdesc(tmp_ctx, b,
6041                                             printer,
6042                                             new_secdesc);
6043
6044 done:
6045         talloc_free(tmp_ctx);
6046         return result;
6047 }
6048
6049 /********************************************************************
6050  Canonicalize printer info from a client
6051  ********************************************************************/
6052
6053 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6054                              struct spoolss_SetPrinterInfo2 *info2,
6055                              int snum)
6056 {
6057         fstring printername;
6058         const char *p;
6059
6060         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6061                 "portname=%s drivername=%s comment=%s location=%s\n",
6062                 info2->servername, info2->printername, info2->sharename,
6063                 info2->portname, info2->drivername, info2->comment,
6064                 info2->location));
6065
6066         /* we force some elements to "correct" values */
6067         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6068         if (info2->servername == NULL) {
6069                 return false;
6070         }
6071         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6072         if (info2->sharename == NULL) {
6073                 return false;
6074         }
6075
6076         /* check to see if we allow printername != sharename */
6077         if (lp_force_printername(snum)) {
6078                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6079                                         lp_netbios_name(), info2->sharename);
6080         } else {
6081                 /* make sure printername is in \\server\printername format */
6082                 fstrcpy(printername, info2->printername);
6083                 p = printername;
6084                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6085                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6086                                 p++;
6087                 }
6088
6089                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6090                                         lp_netbios_name(), p);
6091         }
6092         if (info2->printername == NULL) {
6093                 return false;
6094         }
6095
6096         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6097         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6098
6099         return true;
6100 }
6101
6102 /****************************************************************************
6103 ****************************************************************************/
6104
6105 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6106 {
6107         char *cmd = lp_addport_cmd();
6108         char *command = NULL;
6109         int ret;
6110         bool is_print_op = false;
6111
6112         if ( !*cmd ) {
6113                 return WERR_ACCESS_DENIED;
6114         }
6115
6116         command = talloc_asprintf(ctx,
6117                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6118         if (!command) {
6119                 return WERR_NOMEM;
6120         }
6121
6122         if ( token )
6123                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6124
6125         DEBUG(10,("Running [%s]\n", command));
6126
6127         /********* BEGIN SePrintOperatorPrivilege **********/
6128
6129         if ( is_print_op )
6130                 become_root();
6131
6132         ret = smbrun(command, NULL);
6133
6134         if ( is_print_op )
6135                 unbecome_root();
6136
6137         /********* END SePrintOperatorPrivilege **********/
6138
6139         DEBUGADD(10,("returned [%d]\n", ret));
6140
6141         TALLOC_FREE(command);
6142
6143         if ( ret != 0 ) {
6144                 return WERR_ACCESS_DENIED;
6145         }
6146
6147         return WERR_OK;
6148 }
6149
6150 /****************************************************************************
6151 ****************************************************************************/
6152
6153 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6154                                    int snum)
6155 {
6156         /*
6157          * As we do not know if we are embedded in the file server process
6158          * or not, we have to pretend that all shares are in use.
6159          */
6160         return true;
6161 }
6162
6163 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6164                              struct spoolss_SetPrinterInfo2 *info2,
6165                              const char *remote_machine,
6166                              struct messaging_context *msg_ctx)
6167 {
6168         char *cmd = lp_addprinter_cmd();
6169         char **qlines;
6170         char *command = NULL;
6171         int numlines;
6172         int ret;
6173         int fd;
6174         bool is_print_op = false;
6175
6176         if (!remote_machine) {
6177                 return false;
6178         }
6179
6180         command = talloc_asprintf(ctx,
6181                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6182                         cmd, info2->printername, info2->sharename,
6183                         info2->portname, info2->drivername,
6184                         info2->location, info2->comment, remote_machine);
6185         if (!command) {
6186                 return false;
6187         }
6188
6189         if ( token )
6190                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6191
6192         DEBUG(10,("Running [%s]\n", command));
6193
6194         /********* BEGIN SePrintOperatorPrivilege **********/
6195
6196         if ( is_print_op )
6197                 become_root();
6198
6199         if ( (ret = smbrun(command, &fd)) == 0 ) {
6200                 /* Tell everyone we updated smb.conf. */
6201                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6202         }
6203
6204         if ( is_print_op )
6205                 unbecome_root();
6206
6207         /********* END SePrintOperatorPrivilege **********/
6208
6209         DEBUGADD(10,("returned [%d]\n", ret));
6210
6211         TALLOC_FREE(command);
6212
6213         if ( ret != 0 ) {
6214                 if (fd != -1)
6215                         close(fd);
6216                 return false;
6217         }
6218
6219         /* reload our services immediately */
6220         become_root();
6221         reload_services(NULL, spoolss_conn_snum_used, false);
6222         unbecome_root();
6223
6224         numlines = 0;
6225         /* Get lines and convert them back to dos-codepage */
6226         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6227         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6228         close(fd);
6229
6230         /* Set the portname to what the script says the portname should be. */
6231         /* but don't require anything to be return from the script exit a good error code */
6232
6233         if (numlines) {
6234                 /* Set the portname to what the script says the portname should be. */
6235                 info2->portname = talloc_strdup(ctx, qlines[0]);
6236                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6237         }
6238
6239         TALLOC_FREE(qlines);
6240         return true;
6241 }
6242
6243 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6244                                const struct auth_session_info *session_info,
6245                                struct messaging_context *msg_ctx,
6246                                int snum,
6247                                struct spoolss_SetPrinterInfo2 *printer,
6248                                struct spoolss_PrinterInfo2 *old_printer)
6249 {
6250         bool force_update = (old_printer == NULL);
6251         const char *dnsdomname;
6252         const char *longname;
6253         const char *uncname;
6254         const char *spooling;
6255         DATA_BLOB buffer;
6256         WERROR result = WERR_OK;
6257         struct dcerpc_binding_handle *b;
6258         TALLOC_CTX *tmp_ctx;
6259         bool ok;
6260
6261         tmp_ctx = talloc_new(mem_ctx);
6262         if (!tmp_ctx) {
6263                 return WERR_NOMEM;
6264         }
6265
6266         result = winreg_printer_binding_handle(tmp_ctx,
6267                                                session_info,
6268                                                msg_ctx,
6269                                                &b);
6270         if (!W_ERROR_IS_OK(result)) {
6271                 goto done;
6272         }
6273
6274         if (printer->drivername != NULL &&
6275             (force_update ||
6276              !strequal(printer->drivername, old_printer->drivername))) {
6277                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6278                 if (!ok) {
6279                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6280                         result = WERR_INVALID_DATA;
6281                         goto done;
6282                 }
6283                 result = winreg_set_printer_dataex(tmp_ctx, b,
6284                                           printer->sharename,
6285                                           SPOOL_DSSPOOLER_KEY,
6286                                           SPOOL_REG_DRIVERNAME,
6287                                           REG_SZ,
6288                                           buffer.data,
6289                                           buffer.length);
6290                 if (!W_ERROR_IS_OK(result)) {
6291                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6292                         goto done;
6293                 }
6294
6295                 if (!force_update) {
6296                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6297                                 printer->drivername));
6298
6299                         notify_printer_driver(server_event_context(), msg_ctx,
6300                                               snum, printer->drivername ?
6301                                               printer->drivername : "");
6302                 }
6303         }
6304
6305         if (printer->comment != NULL &&
6306             (force_update ||
6307              !strequal(printer->comment, old_printer->comment))) {
6308                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6309                 if (!ok) {
6310                         DEBUG(0, ("comment data corrupted\n"));
6311                         result = WERR_INVALID_DATA;
6312                         goto done;
6313                 }
6314                 result = winreg_set_printer_dataex(tmp_ctx, b,
6315                                           printer->sharename,
6316                                           SPOOL_DSSPOOLER_KEY,
6317                                           SPOOL_REG_DESCRIPTION,
6318                                           REG_SZ,
6319                                           buffer.data,
6320                                           buffer.length);
6321                 if (!W_ERROR_IS_OK(result)) {
6322                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6323                         goto done;
6324                 }
6325
6326                 if (!force_update) {
6327                         notify_printer_comment(server_event_context(), msg_ctx,
6328                                                snum, printer->comment ?
6329                                                printer->comment : "");
6330                 }
6331         }
6332
6333         if (printer->sharename != NULL &&
6334             (force_update ||
6335              !strequal(printer->sharename, old_printer->sharename))) {
6336                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6337                 if (!ok) {
6338                         DEBUG(0, ("sharename data corrupted\n"));
6339                         result = WERR_INVALID_DATA;
6340                         goto done;
6341                 }
6342                 result = winreg_set_printer_dataex(tmp_ctx, b,
6343                                           printer->sharename,
6344                                           SPOOL_DSSPOOLER_KEY,
6345                                           SPOOL_REG_PRINTSHARENAME,
6346                                           REG_SZ,
6347                                           buffer.data,
6348                                           buffer.length);
6349                 if (!W_ERROR_IS_OK(result)) {
6350                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6351                         goto done;
6352                 }
6353
6354                 if (!force_update) {
6355                         notify_printer_sharename(server_event_context(),
6356                                                  msg_ctx,
6357                                                  snum, printer->sharename ?
6358                                                  printer->sharename : "");
6359                 }
6360         }
6361
6362         if (printer->printername != NULL &&
6363             (force_update ||
6364              !strequal(printer->printername, old_printer->printername))) {
6365                 const char *p;
6366
6367                 p = strrchr(printer->printername, '\\' );
6368                 if (p != NULL) {
6369                         p++;
6370                 } else {
6371                         p = printer->printername;
6372                 }
6373
6374                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6375                 if (!ok) {
6376                         DEBUG(0, ("printername data corrupted\n"));
6377                         result = WERR_INVALID_DATA;
6378                         goto done;
6379                 }
6380                 result = winreg_set_printer_dataex(tmp_ctx, b,
6381                                           printer->sharename,
6382                                           SPOOL_DSSPOOLER_KEY,
6383                                           SPOOL_REG_PRINTERNAME,
6384                                           REG_SZ,
6385                                           buffer.data,
6386                                           buffer.length);
6387                 if (!W_ERROR_IS_OK(result)) {
6388                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6389                         goto done;
6390                 }
6391
6392                 if (!force_update) {
6393                         notify_printer_printername(server_event_context(),
6394                                                    msg_ctx, snum, p ? p : "");
6395                 }
6396         }
6397
6398         if (printer->portname != NULL &&
6399             (force_update ||
6400              !strequal(printer->portname, old_printer->portname))) {
6401                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6402                 if (!ok) {
6403                         DEBUG(0, ("portname data corrupted\n"));
6404                         result = WERR_INVALID_DATA;
6405                         goto done;
6406                 }
6407                 result = winreg_set_printer_dataex(tmp_ctx, b,
6408                                           printer->sharename,
6409                                           SPOOL_DSSPOOLER_KEY,
6410                                           SPOOL_REG_PORTNAME,
6411                                           REG_SZ,
6412                                           buffer.data,
6413                                           buffer.length);
6414                 if (!W_ERROR_IS_OK(result)) {
6415                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6416                         goto done;
6417                 }
6418
6419                 if (!force_update) {
6420                         notify_printer_port(server_event_context(),
6421                                             msg_ctx, snum, printer->portname ?
6422                                             printer->portname : "");
6423                 }
6424         }
6425
6426         if (printer->location != NULL &&
6427             (force_update ||
6428              !strequal(printer->location, old_printer->location))) {
6429                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6430                 if (!ok) {
6431                         DEBUG(0, ("location data corrupted\n"));
6432                         result = WERR_INVALID_DATA;
6433                         goto done;
6434                 }
6435                 result = winreg_set_printer_dataex(tmp_ctx, b,
6436                                           printer->sharename,
6437                                           SPOOL_DSSPOOLER_KEY,
6438                                           SPOOL_REG_LOCATION,
6439                                           REG_SZ,
6440                                           buffer.data,
6441                                           buffer.length);
6442                 if (!W_ERROR_IS_OK(result)) {
6443                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6444                         goto done;
6445                 }
6446
6447                 if (!force_update) {
6448                         notify_printer_location(server_event_context(),
6449                                                 msg_ctx, snum,
6450                                                 printer->location ?
6451                                                 printer->location : "");
6452                 }
6453         }
6454
6455         if (printer->sepfile != NULL &&
6456             (force_update ||
6457              !strequal(printer->sepfile, old_printer->sepfile))) {
6458                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6459                 if (!ok) {
6460                         DEBUG(0, ("sepfile data corrupted\n"));
6461                         result = WERR_INVALID_DATA;
6462                         goto done;
6463                 }
6464                 result = winreg_set_printer_dataex(tmp_ctx, b,
6465                                           printer->sharename,
6466                                           SPOOL_DSSPOOLER_KEY,
6467                                           SPOOL_REG_PRINTSEPARATORFILE,
6468                                           REG_SZ,
6469                                           buffer.data,
6470                                           buffer.length);
6471                 if (!W_ERROR_IS_OK(result)) {
6472                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6473                         goto done;
6474                 }
6475
6476                 if (!force_update) {
6477                         notify_printer_sepfile(server_event_context(),
6478                                                msg_ctx, snum,
6479                                                printer->sepfile ?
6480                                                printer->sepfile : "");
6481                 }
6482         }
6483
6484         if (printer->starttime != 0 &&
6485             (force_update ||
6486              printer->starttime != old_printer->starttime)) {
6487                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6488                 SIVAL(buffer.data, 0, printer->starttime);
6489                 result = winreg_set_printer_dataex(tmp_ctx, b,
6490                                           printer->sharename,
6491                                           SPOOL_DSSPOOLER_KEY,
6492                                           SPOOL_REG_PRINTSTARTTIME,
6493                                           REG_DWORD,
6494                                           buffer.data,
6495                                           buffer.length);
6496                 if (!W_ERROR_IS_OK(result)) {
6497                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6498                         goto done;
6499                 }
6500         }
6501
6502         if (printer->untiltime != 0 &&
6503             (force_update ||
6504              printer->untiltime != old_printer->untiltime)) {
6505                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6506                 SIVAL(buffer.data, 0, printer->untiltime);
6507                 result = winreg_set_printer_dataex(tmp_ctx, b,
6508                                           printer->sharename,
6509                                           SPOOL_DSSPOOLER_KEY,
6510                                           SPOOL_REG_PRINTENDTIME,
6511                                           REG_DWORD,
6512                                           buffer.data,
6513                                           buffer.length);
6514                 if (!W_ERROR_IS_OK(result)) {
6515                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6516                         goto done;
6517                 }
6518         }
6519
6520         if (force_update || printer->priority != old_printer->priority) {
6521                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6522                 SIVAL(buffer.data, 0, printer->priority);
6523                 result = winreg_set_printer_dataex(tmp_ctx, b,
6524                                           printer->sharename,
6525                                           SPOOL_DSSPOOLER_KEY,
6526                                           SPOOL_REG_PRIORITY,
6527                                           REG_DWORD,
6528                                           buffer.data,
6529                                           buffer.length);
6530                 if (!W_ERROR_IS_OK(result)) {
6531                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6532                         goto done;
6533                 }
6534         }
6535
6536         if (force_update || printer->attributes != old_printer->attributes) {
6537                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6538                 SIVAL(buffer.data, 0, (printer->attributes &
6539                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6540                 result = winreg_set_printer_dataex(tmp_ctx, b,
6541                                           printer->sharename,
6542                                           SPOOL_DSSPOOLER_KEY,
6543                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6544                                           REG_DWORD,
6545                                           buffer.data,
6546                                           buffer.length);
6547                 if (!W_ERROR_IS_OK(result)) {
6548                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6549                         goto done;
6550                 }
6551
6552                 switch (printer->attributes & 0x3) {
6553                         case 0:
6554                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6555                                 break;
6556                         case 1:
6557                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6558                                 break;
6559                         case 2:
6560                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6561                                 break;
6562                         default:
6563                                 spooling = "unknown";
6564                 }
6565                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6566                 if (!ok) {
6567                         DEBUG(0, ("printSpooling data corrupted\n"));
6568                         result = WERR_INVALID_DATA;
6569                         goto done;
6570                 }
6571                 winreg_set_printer_dataex(tmp_ctx, b,
6572                                           printer->sharename,
6573                                           SPOOL_DSSPOOLER_KEY,
6574                                           SPOOL_REG_PRINTSPOOLING,
6575                                           REG_SZ,
6576                                           buffer.data,
6577                                           buffer.length);
6578         }
6579
6580         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6581         if (!ok) {
6582                 DEBUG(0, ("shortServerName data corrupted\n"));
6583                 result = WERR_INVALID_DATA;
6584                 goto done;
6585         }
6586         result = winreg_set_printer_dataex(tmp_ctx, b,
6587                                   printer->sharename,
6588                                   SPOOL_DSSPOOLER_KEY,
6589                                   SPOOL_REG_SHORTSERVERNAME,
6590                                   REG_SZ,
6591                                   buffer.data,
6592                                   buffer.length);
6593         if (!W_ERROR_IS_OK(result)) {
6594                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6595                 goto done;
6596         }
6597
6598         dnsdomname = get_mydnsfullname();
6599         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6600                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6601         } else {
6602                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6603         }
6604         if (longname == NULL) {
6605                 result = WERR_NOMEM;
6606                 goto done;
6607         }
6608
6609         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6610         if (!ok) {
6611                 DEBUG(0, ("longname data corrupted\n"));
6612                 result = WERR_INVALID_DATA;
6613                 goto done;
6614         }
6615         result = winreg_set_printer_dataex(tmp_ctx, b,
6616                                            printer->sharename,
6617                                            SPOOL_DSSPOOLER_KEY,
6618                                            SPOOL_REG_SERVERNAME,
6619                                            REG_SZ,
6620                                            buffer.data,
6621                                            buffer.length);
6622         if (!W_ERROR_IS_OK(result)) {
6623                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6624                 goto done;
6625         }
6626
6627         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6628                                   lp_netbios_name(), printer->sharename);
6629         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6630         if (!ok) {
6631                 DEBUG(0, ("uncName 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_UNCNAME,
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_UNCNAME));
6644                 goto done;
6645         }
6646
6647 done:
6648         talloc_free(tmp_ctx);
6649         return result;
6650 }
6651
6652 /********************************************************************
6653  * Called by spoolss_api_setprinter
6654  * when updating a printer description.
6655  ********************************************************************/
6656
6657 static WERROR update_printer(struct pipes_struct *p,
6658                              struct policy_handle *handle,
6659                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6660                              struct spoolss_DeviceMode *devmode)
6661 {
6662         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6663         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6664         struct spoolss_PrinterInfo2 *old_printer;
6665         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6666         int snum;
6667         WERROR result = WERR_OK;
6668         TALLOC_CTX *tmp_ctx;
6669         struct dcerpc_binding_handle *b;
6670
6671         DEBUG(8,("update_printer\n"));
6672
6673         tmp_ctx = talloc_new(p->mem_ctx);
6674         if (tmp_ctx == NULL) {
6675                 return WERR_NOMEM;
6676         }
6677
6678         if (!Printer) {
6679                 result = WERR_BADFID;
6680                 goto done;
6681         }
6682
6683         if (!get_printer_snum(p, handle, &snum, NULL)) {
6684                 result = WERR_BADFID;
6685                 goto done;
6686         }
6687
6688         result = winreg_printer_binding_handle(tmp_ctx,
6689                                                get_session_info_system(),
6690                                                p->msg_ctx,
6691                                                &b);
6692         if (!W_ERROR_IS_OK(result)) {
6693                 goto done;
6694         }
6695
6696         result = winreg_get_printer(tmp_ctx, b,
6697                                     lp_const_servicename(snum),
6698                                     &old_printer);
6699         if (!W_ERROR_IS_OK(result)) {
6700                 result = WERR_BADFID;
6701                 goto done;
6702         }
6703
6704         /* Do sanity check on the requested changes for Samba */
6705         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6706                 result = WERR_INVALID_PARAM;
6707                 goto done;
6708         }
6709
6710         /* FIXME!!! If the driver has changed we really should verify that
6711            it is installed before doing much else   --jerry */
6712
6713         /* Check calling user has permission to update printer description */
6714         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6715                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6716                 result = WERR_ACCESS_DENIED;
6717                 goto done;
6718         }
6719
6720         /* Call addprinter hook */
6721         /* Check changes to see if this is really needed */
6722
6723         if (*lp_addprinter_cmd() &&
6724                         (!strequal(printer->drivername, old_printer->drivername) ||
6725                          !strequal(printer->comment, old_printer->comment) ||
6726                          !strequal(printer->portname, old_printer->portname) ||
6727                          !strequal(printer->location, old_printer->location)) )
6728         {
6729                 char *raddr;
6730
6731                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6732                                                          p->mem_ctx);
6733                 if (raddr == NULL) {
6734                         return WERR_NOMEM;
6735                 }
6736
6737                 /* add_printer_hook() will call reload_services() */
6738                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6739                                       printer, raddr,
6740                                       p->msg_ctx)) {
6741                         result = WERR_ACCESS_DENIED;
6742                         goto done;
6743                 }
6744         }
6745
6746         result = update_dsspooler(tmp_ctx,
6747                                   get_session_info_system(),
6748                                   p->msg_ctx,
6749                                   snum,
6750                                   printer,
6751                                   old_printer);
6752         if (!W_ERROR_IS_OK(result)) {
6753                 goto done;
6754         }
6755
6756         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6757
6758         if (devmode == NULL) {
6759                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6760         }
6761         result = winreg_update_printer(tmp_ctx, b,
6762                                        printer->sharename,
6763                                        printer_mask,
6764                                        printer,
6765                                        devmode,
6766                                        NULL);
6767
6768 done:
6769         talloc_free(tmp_ctx);
6770
6771         return result;
6772 }
6773
6774 /****************************************************************************
6775 ****************************************************************************/
6776 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6777                                            struct policy_handle *handle,
6778                                            struct spoolss_SetPrinterInfo7 *info7)
6779 {
6780 #ifdef HAVE_ADS
6781         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6782         WERROR result;
6783         int snum;
6784         struct printer_handle *Printer;
6785
6786         if ( lp_security() != SEC_ADS ) {
6787                 return WERR_UNKNOWN_LEVEL;
6788         }
6789
6790         Printer = find_printer_index_by_hnd(p, handle);
6791
6792         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6793
6794         if (!Printer)
6795                 return WERR_BADFID;
6796
6797         if (!get_printer_snum(p, handle, &snum, NULL))
6798                 return WERR_BADFID;
6799
6800         result = winreg_get_printer_internal(p->mem_ctx,
6801                                     get_session_info_system(),
6802                                     p->msg_ctx,
6803                                     lp_servicename(snum),
6804                                     &pinfo2);
6805         if (!W_ERROR_IS_OK(result)) {
6806                 return WERR_BADFID;
6807         }
6808
6809         nt_printer_publish(pinfo2,
6810                            get_session_info_system(),
6811                            p->msg_ctx,
6812                            pinfo2,
6813                            info7->action);
6814
6815         TALLOC_FREE(pinfo2);
6816         return WERR_OK;
6817 #else
6818         return WERR_UNKNOWN_LEVEL;
6819 #endif
6820 }
6821
6822 /********************************************************************
6823  ********************************************************************/
6824
6825 static WERROR update_printer_devmode(struct pipes_struct *p,
6826                                      struct policy_handle *handle,
6827                                      struct spoolss_DeviceMode *devmode)
6828 {
6829         int snum;
6830         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6831         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6832
6833         DEBUG(8,("update_printer_devmode\n"));
6834
6835         if (!Printer) {
6836                 return WERR_BADFID;
6837         }
6838
6839         if (!get_printer_snum(p, handle, &snum, NULL)) {
6840                 return WERR_BADFID;
6841         }
6842
6843         /* Check calling user has permission to update printer description */
6844         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6845                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6846                 return WERR_ACCESS_DENIED;
6847         }
6848
6849         return winreg_update_printer_internal(p->mem_ctx,
6850                                      get_session_info_system(),
6851                                      p->msg_ctx,
6852                                      lp_const_servicename(snum),
6853                                      info2_mask,
6854                                      NULL,
6855                                      devmode,
6856                                      NULL);
6857 }
6858
6859
6860 /****************************************************************
6861  _spoolss_SetPrinter
6862 ****************************************************************/
6863
6864 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6865                            struct spoolss_SetPrinter *r)
6866 {
6867         WERROR result;
6868
6869         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6870
6871         if (!Printer) {
6872                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6873                         OUR_HANDLE(r->in.handle)));
6874                 return WERR_BADFID;
6875         }
6876
6877         /* check the level */
6878         switch (r->in.info_ctr->level) {
6879                 case 0:
6880                         return control_printer(r->in.handle, r->in.command, p);
6881                 case 2:
6882                         result = update_printer(p, r->in.handle,
6883                                                 r->in.info_ctr,
6884                                                 r->in.devmode_ctr->devmode);
6885                         if (!W_ERROR_IS_OK(result))
6886                                 return result;
6887                         if (r->in.secdesc_ctr->sd)
6888                                 result = update_printer_sec(r->in.handle, p,
6889                                                             r->in.secdesc_ctr);
6890                         return result;
6891                 case 3:
6892                         return update_printer_sec(r->in.handle, p,
6893                                                   r->in.secdesc_ctr);
6894                 case 7:
6895                         return publish_or_unpublish_printer(p, r->in.handle,
6896                                                             r->in.info_ctr->info.info7);
6897                 case 8:
6898                         return update_printer_devmode(p, r->in.handle,
6899                                                       r->in.devmode_ctr->devmode);
6900                 default:
6901                         return WERR_UNKNOWN_LEVEL;
6902         }
6903 }
6904
6905 /****************************************************************
6906  _spoolss_FindClosePrinterNotify
6907 ****************************************************************/
6908
6909 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6910                                        struct spoolss_FindClosePrinterNotify *r)
6911 {
6912         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6913
6914         if (!Printer) {
6915                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6916                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6917                 return WERR_BADFID;
6918         }
6919
6920         if (Printer->notify.cli_chan != NULL &&
6921             Printer->notify.cli_chan->active_connections > 0) {
6922                 int snum = -1;
6923
6924                 if (Printer->printer_type == SPLHND_PRINTER) {
6925                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6926                                 return WERR_BADFID;
6927                         }
6928                 }
6929
6930                 srv_spoolss_replycloseprinter(snum, Printer);
6931         }
6932
6933         Printer->notify.flags=0;
6934         Printer->notify.options=0;
6935         Printer->notify.localmachine[0]='\0';
6936         Printer->notify.printerlocal=0;
6937         TALLOC_FREE(Printer->notify.option);
6938
6939         return WERR_OK;
6940 }
6941
6942 /****************************************************************
6943  _spoolss_AddJob
6944 ****************************************************************/
6945
6946 WERROR _spoolss_AddJob(struct pipes_struct *p,
6947                        struct spoolss_AddJob *r)
6948 {
6949         if (!r->in.buffer && (r->in.offered != 0)) {
6950                 return WERR_INVALID_PARAM;
6951         }
6952
6953         /* this is what a NT server returns for AddJob. AddJob must fail on
6954          * non-local printers */
6955
6956         if (r->in.level != 1) {
6957                 return WERR_UNKNOWN_LEVEL;
6958         }
6959
6960         return WERR_INVALID_PARAM;
6961 }
6962
6963 /****************************************************************************
6964 fill_job_info1
6965 ****************************************************************************/
6966
6967 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6968                              struct spoolss_JobInfo1 *r,
6969                              const print_queue_struct *queue,
6970                              int position, int snum,
6971                              struct spoolss_PrinterInfo2 *pinfo2)
6972 {
6973         struct tm *t;
6974
6975         t = gmtime(&queue->time);
6976
6977         r->job_id               = queue->job;
6978
6979         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6980         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6981         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6982         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6983         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6984         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6985         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6986         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6987         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6988         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6989         r->text_status          = talloc_strdup(mem_ctx, "");
6990         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6991
6992         r->status               = nt_printj_status(queue->status);
6993         r->priority             = queue->priority;
6994         r->position             = position;
6995         r->total_pages          = queue->page_count;
6996         r->pages_printed        = 0; /* ??? */
6997
6998         init_systemtime(&r->submitted, t);
6999
7000         return WERR_OK;
7001 }
7002
7003 /****************************************************************************
7004 fill_job_info2
7005 ****************************************************************************/
7006
7007 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7008                              struct spoolss_JobInfo2 *r,
7009                              const print_queue_struct *queue,
7010                              int position, int snum,
7011                              struct spoolss_PrinterInfo2 *pinfo2,
7012                              struct spoolss_DeviceMode *devmode)
7013 {
7014         struct tm *t;
7015
7016         t = gmtime(&queue->time);
7017
7018         r->job_id               = queue->job;
7019
7020         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
7021         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7022         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7023         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7024         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7025         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7026         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7027         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7028         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7029         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7030         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7031         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7032         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7033         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7034         r->parameters           = talloc_strdup(mem_ctx, "");
7035         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7036         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7037         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7038
7039         r->devmode              = devmode;
7040
7041         r->text_status          = talloc_strdup(mem_ctx, "");
7042         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7043
7044         r->secdesc              = NULL;
7045
7046         r->status               = nt_printj_status(queue->status);
7047         r->priority             = queue->priority;
7048         r->position             = position;
7049         r->start_time           = 0;
7050         r->until_time           = 0;
7051         r->total_pages          = queue->page_count;
7052         r->size                 = queue->size;
7053         init_systemtime(&r->submitted, t);
7054         r->time                 = 0;
7055         r->pages_printed        = 0; /* ??? */
7056
7057         return WERR_OK;
7058 }
7059
7060 /****************************************************************************
7061 fill_job_info3
7062 ****************************************************************************/
7063
7064 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7065                              struct spoolss_JobInfo3 *r,
7066                              const print_queue_struct *queue,
7067                              const print_queue_struct *next_queue,
7068                              int position, int snum,
7069                              struct spoolss_PrinterInfo2 *pinfo2)
7070 {
7071         r->job_id               = queue->job;
7072         r->next_job_id          = 0;
7073         if (next_queue) {
7074                 r->next_job_id  = next_queue->job;
7075         }
7076         r->reserved             = 0;
7077
7078         return WERR_OK;
7079 }
7080
7081 /****************************************************************************
7082  Enumjobs at level 1.
7083 ****************************************************************************/
7084
7085 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7086                               const print_queue_struct *queue,
7087                               uint32_t num_queues, int snum,
7088                               struct spoolss_PrinterInfo2 *pinfo2,
7089                               union spoolss_JobInfo **info_p,
7090                               uint32_t *count)
7091 {
7092         union spoolss_JobInfo *info;
7093         int i;
7094         WERROR result = WERR_OK;
7095
7096         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7097         W_ERROR_HAVE_NO_MEMORY(info);
7098
7099         *count = num_queues;
7100
7101         for (i=0; i<*count; i++) {
7102                 result = fill_job_info1(info,
7103                                         &info[i].info1,
7104                                         &queue[i],
7105                                         i,
7106                                         snum,
7107                                         pinfo2);
7108                 if (!W_ERROR_IS_OK(result)) {
7109                         goto out;
7110                 }
7111         }
7112
7113  out:
7114         if (!W_ERROR_IS_OK(result)) {
7115                 TALLOC_FREE(info);
7116                 *count = 0;
7117                 return result;
7118         }
7119
7120         *info_p = info;
7121
7122         return WERR_OK;
7123 }
7124
7125 /****************************************************************************
7126  Enumjobs at level 2.
7127 ****************************************************************************/
7128
7129 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7130                               const print_queue_struct *queue,
7131                               uint32_t num_queues, int snum,
7132                               struct spoolss_PrinterInfo2 *pinfo2,
7133                               union spoolss_JobInfo **info_p,
7134                               uint32_t *count)
7135 {
7136         union spoolss_JobInfo *info;
7137         int i;
7138         WERROR result = WERR_OK;
7139
7140         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7141         W_ERROR_HAVE_NO_MEMORY(info);
7142
7143         *count = num_queues;
7144
7145         for (i=0; i<*count; i++) {
7146                 struct spoolss_DeviceMode *devmode;
7147
7148                 result = spoolss_create_default_devmode(info,
7149                                                         pinfo2->printername,
7150                                                         &devmode);
7151                 if (!W_ERROR_IS_OK(result)) {
7152                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7153                         goto out;
7154                 }
7155
7156                 result = fill_job_info2(info,
7157                                         &info[i].info2,
7158                                         &queue[i],
7159                                         i,
7160                                         snum,
7161                                         pinfo2,
7162                                         devmode);
7163                 if (!W_ERROR_IS_OK(result)) {
7164                         goto out;
7165                 }
7166         }
7167
7168  out:
7169         if (!W_ERROR_IS_OK(result)) {
7170                 TALLOC_FREE(info);
7171                 *count = 0;
7172                 return result;
7173         }
7174
7175         *info_p = info;
7176
7177         return WERR_OK;
7178 }
7179
7180 /****************************************************************************
7181  Enumjobs at level 3.
7182 ****************************************************************************/
7183
7184 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7185                               const print_queue_struct *queue,
7186                               uint32_t num_queues, int snum,
7187                               struct spoolss_PrinterInfo2 *pinfo2,
7188                               union spoolss_JobInfo **info_p,
7189                               uint32_t *count)
7190 {
7191         union spoolss_JobInfo *info;
7192         int i;
7193         WERROR result = WERR_OK;
7194
7195         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7196         W_ERROR_HAVE_NO_MEMORY(info);
7197
7198         *count = num_queues;
7199
7200         for (i=0; i<*count; i++) {
7201                 const print_queue_struct *next_queue = NULL;
7202
7203                 if (i+1 < *count) {
7204                         next_queue = &queue[i+1];
7205                 }
7206
7207                 result = fill_job_info3(info,
7208                                         &info[i].info3,
7209                                         &queue[i],
7210                                         next_queue,
7211                                         i,
7212                                         snum,
7213                                         pinfo2);
7214                 if (!W_ERROR_IS_OK(result)) {
7215                         goto out;
7216                 }
7217         }
7218
7219  out:
7220         if (!W_ERROR_IS_OK(result)) {
7221                 TALLOC_FREE(info);
7222                 *count = 0;
7223                 return result;
7224         }
7225
7226         *info_p = info;
7227
7228         return WERR_OK;
7229 }
7230
7231 /****************************************************************
7232  _spoolss_EnumJobs
7233 ****************************************************************/
7234
7235 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7236                          struct spoolss_EnumJobs *r)
7237 {
7238         WERROR result;
7239         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7240         int snum;
7241         print_status_struct prt_status;
7242         print_queue_struct *queue = NULL;
7243         uint32_t count;
7244
7245         /* that's an [in out] buffer */
7246
7247         if (!r->in.buffer && (r->in.offered != 0)) {
7248                 return WERR_INVALID_PARAM;
7249         }
7250
7251         DEBUG(4,("_spoolss_EnumJobs\n"));
7252
7253         *r->out.needed = 0;
7254         *r->out.count = 0;
7255         *r->out.info = NULL;
7256
7257         /* lookup the printer snum and tdb entry */
7258
7259         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7260                 return WERR_BADFID;
7261         }
7262
7263         result = winreg_get_printer_internal(p->mem_ctx,
7264                                     get_session_info_system(),
7265                                     p->msg_ctx,
7266                                     lp_const_servicename(snum),
7267                                     &pinfo2);
7268         if (!W_ERROR_IS_OK(result)) {
7269                 return result;
7270         }
7271
7272         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7273         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7274                 count, prt_status.status, prt_status.message));
7275
7276         if (count == 0) {
7277                 SAFE_FREE(queue);
7278                 TALLOC_FREE(pinfo2);
7279                 return WERR_OK;
7280         }
7281
7282         switch (r->in.level) {
7283         case 1:
7284                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7285                                          pinfo2, r->out.info, r->out.count);
7286                 break;
7287         case 2:
7288                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7289                                          pinfo2, r->out.info, r->out.count);
7290                 break;
7291         case 3:
7292                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7293                                          pinfo2, r->out.info, r->out.count);
7294                 break;
7295         default:
7296                 result = WERR_UNKNOWN_LEVEL;
7297                 break;
7298         }
7299
7300         SAFE_FREE(queue);
7301         TALLOC_FREE(pinfo2);
7302
7303         if (!W_ERROR_IS_OK(result)) {
7304                 return result;
7305         }
7306
7307         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7308                                                      spoolss_EnumJobs,
7309                                                      *r->out.info, r->in.level,
7310                                                      *r->out.count);
7311         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7312         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7313
7314         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7315 }
7316
7317 /****************************************************************
7318  _spoolss_ScheduleJob
7319 ****************************************************************/
7320
7321 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7322                             struct spoolss_ScheduleJob *r)
7323 {
7324         return WERR_OK;
7325 }
7326
7327 /****************************************************************
7328 ****************************************************************/
7329
7330 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7331                                struct messaging_context *msg_ctx,
7332                                const char *printer_name,
7333                                uint32_t job_id,
7334                                struct spoolss_SetJobInfo1 *r)
7335 {
7336         char *old_doc_name;
7337
7338         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7339                 return WERR_BADFID;
7340         }
7341
7342         if (strequal(old_doc_name, r->document_name)) {
7343                 return WERR_OK;
7344         }
7345
7346         if (!print_job_set_name(server_event_context(), msg_ctx,
7347                                 printer_name, job_id, r->document_name)) {
7348                 return WERR_BADFID;
7349         }
7350
7351         return WERR_OK;
7352 }
7353
7354 /****************************************************************
7355  _spoolss_SetJob
7356 ****************************************************************/
7357
7358 WERROR _spoolss_SetJob(struct pipes_struct *p,
7359                        struct spoolss_SetJob *r)
7360 {
7361         const struct auth_session_info *session_info = p->session_info;
7362         int snum;
7363         WERROR errcode = WERR_BADFUNC;
7364
7365         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7366                 return WERR_BADFID;
7367         }
7368
7369         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7370                 return WERR_INVALID_PRINTER_NAME;
7371         }
7372
7373         switch (r->in.command) {
7374         case SPOOLSS_JOB_CONTROL_CANCEL:
7375         case SPOOLSS_JOB_CONTROL_DELETE:
7376                 errcode = print_job_delete(session_info, p->msg_ctx,
7377                                            snum, r->in.job_id);
7378                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7379                         errcode = WERR_OK;
7380                 }
7381                 break;
7382         case SPOOLSS_JOB_CONTROL_PAUSE:
7383                 if (print_job_pause(session_info, p->msg_ctx,
7384                                     snum, r->in.job_id, &errcode)) {
7385                         errcode = WERR_OK;
7386                 }
7387                 break;
7388         case SPOOLSS_JOB_CONTROL_RESTART:
7389         case SPOOLSS_JOB_CONTROL_RESUME:
7390                 if (print_job_resume(session_info, p->msg_ctx,
7391                                      snum, r->in.job_id, &errcode)) {
7392                         errcode = WERR_OK;
7393                 }
7394                 break;
7395         case 0:
7396                 errcode = WERR_OK;
7397                 break;
7398         default:
7399                 return WERR_UNKNOWN_LEVEL;
7400         }
7401
7402         if (!W_ERROR_IS_OK(errcode)) {
7403                 return errcode;
7404         }
7405
7406         if (r->in.ctr == NULL) {
7407                 return errcode;
7408         }
7409
7410         switch (r->in.ctr->level) {
7411         case 1:
7412                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7413                                            lp_const_servicename(snum),
7414                                            r->in.job_id,
7415                                            r->in.ctr->info.info1);
7416                 break;
7417         case 2:
7418         case 3:
7419         case 4:
7420         default:
7421                 return WERR_UNKNOWN_LEVEL;
7422         }
7423
7424         return errcode;
7425 }
7426
7427 /****************************************************************************
7428  Enumerates all printer drivers by level and architecture.
7429 ****************************************************************************/
7430
7431 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7432                                                        const struct auth_session_info *session_info,
7433                                                        struct messaging_context *msg_ctx,
7434                                                        const char *servername,
7435                                                        const char *architecture,
7436                                                        uint32_t level,
7437                                                        union spoolss_DriverInfo **info_p,
7438                                                        uint32_t *count_p)
7439 {
7440         int i;
7441         uint32_t version;
7442         struct spoolss_DriverInfo8 *driver;
7443         union spoolss_DriverInfo *info = NULL;
7444         uint32_t count = 0;
7445         WERROR result = WERR_OK;
7446         uint32_t num_drivers;
7447         const char **drivers;
7448         struct dcerpc_binding_handle *b;
7449         TALLOC_CTX *tmp_ctx = NULL;
7450
7451         *count_p = 0;
7452         *info_p = NULL;
7453
7454         tmp_ctx = talloc_new(mem_ctx);
7455         if (!tmp_ctx) {
7456                 return WERR_NOMEM;
7457         }
7458
7459         result = winreg_printer_binding_handle(tmp_ctx,
7460                                                session_info,
7461                                                msg_ctx,
7462                                                &b);
7463         if (!W_ERROR_IS_OK(result)) {
7464                 goto out;
7465         }
7466
7467         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7468                 result = winreg_get_driver_list(tmp_ctx, b,
7469                                                 architecture, version,
7470                                                 &num_drivers, &drivers);
7471                 if (!W_ERROR_IS_OK(result)) {
7472                         goto out;
7473                 }
7474                 DEBUG(4, ("we have:[%d] drivers in environment"
7475                           " [%s] and version [%d]\n",
7476                           num_drivers, architecture, version));
7477
7478                 if (num_drivers != 0) {
7479                         info = talloc_realloc(tmp_ctx, info,
7480                                                     union spoolss_DriverInfo,
7481                                                     count + num_drivers);
7482                         if (!info) {
7483                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7484                                         "failed to enlarge driver info buffer!\n"));
7485                                 result = WERR_NOMEM;
7486                                 goto out;
7487                         }
7488                 }
7489
7490                 for (i = 0; i < num_drivers; i++) {
7491                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7492
7493                         result = winreg_get_driver(tmp_ctx, b,
7494                                                    architecture, drivers[i],
7495                                                    version, &driver);
7496                         if (!W_ERROR_IS_OK(result)) {
7497                                 goto out;
7498                         }
7499
7500                         switch (level) {
7501                         case 1:
7502                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7503                                                                    driver, servername);
7504                                 break;
7505                         case 2:
7506                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7507                                                                    driver, servername);
7508                                 break;
7509                         case 3:
7510                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7511                                                                    driver, servername);
7512                                 break;
7513                         case 4:
7514                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7515                                                                    driver, servername);
7516                                 break;
7517                         case 5:
7518                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7519                                                                    driver, servername);
7520                                 break;
7521                         case 6:
7522                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7523                                                                    driver, servername);
7524                                 break;
7525                         case 8:
7526                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7527                                                                    driver, servername);
7528                                 break;
7529                         default:
7530                                 result = WERR_UNKNOWN_LEVEL;
7531                                 break;
7532                         }
7533
7534                         TALLOC_FREE(driver);
7535
7536                         if (!W_ERROR_IS_OK(result)) {
7537                                 goto out;
7538                         }
7539                 }
7540
7541                 count += num_drivers;
7542                 TALLOC_FREE(drivers);
7543         }
7544
7545 out:
7546         if (W_ERROR_IS_OK(result)) {
7547                 *info_p = talloc_move(mem_ctx, &info);
7548                 *count_p = count;
7549         }
7550
7551         talloc_free(tmp_ctx);
7552         return result;
7553 }
7554
7555 /****************************************************************************
7556  Enumerates all printer drivers by level.
7557 ****************************************************************************/
7558
7559 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7560                                        const struct auth_session_info *session_info,
7561                                        struct messaging_context *msg_ctx,
7562                                        const char *servername,
7563                                        const char *architecture,
7564                                        uint32_t level,
7565                                        union spoolss_DriverInfo **info_p,
7566                                        uint32_t *count_p)
7567 {
7568         uint32_t a,i;
7569         WERROR result = WERR_OK;
7570
7571         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7572
7573                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7574
7575                         union spoolss_DriverInfo *info = NULL;
7576                         uint32_t count = 0;
7577
7578                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7579                                                                           session_info,
7580                                                                           msg_ctx,
7581                                                                           servername,
7582                                                                           archi_table[a].long_archi,
7583                                                                           level,
7584                                                                           &info,
7585                                                                           &count);
7586                         if (!W_ERROR_IS_OK(result)) {
7587                                 continue;
7588                         }
7589
7590                         for (i=0; i < count; i++) {
7591                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7592                                              info[i], info_p, count_p);
7593                         }
7594                 }
7595
7596                 return result;
7597         }
7598
7599         return enumprinterdrivers_level_by_architecture(mem_ctx,
7600                                                         session_info,
7601                                                         msg_ctx,
7602                                                         servername,
7603                                                         architecture,
7604                                                         level,
7605                                                         info_p,
7606                                                         count_p);
7607 }
7608
7609 /****************************************************************
7610  _spoolss_EnumPrinterDrivers
7611 ****************************************************************/
7612
7613 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7614                                    struct spoolss_EnumPrinterDrivers *r)
7615 {
7616         const char *cservername;
7617         WERROR result;
7618
7619         /* that's an [in out] buffer */
7620
7621         if (!r->in.buffer && (r->in.offered != 0)) {
7622                 return WERR_INVALID_PARAM;
7623         }
7624
7625         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7626
7627         *r->out.needed = 0;
7628         *r->out.count = 0;
7629         *r->out.info = NULL;
7630
7631         cservername = canon_servername(r->in.server);
7632
7633         if (!is_myname_or_ipaddr(cservername)) {
7634                 return WERR_UNKNOWN_PRINTER_DRIVER;
7635         }
7636
7637         result = enumprinterdrivers_level(p->mem_ctx,
7638                                           get_session_info_system(),
7639                                           p->msg_ctx,
7640                                           cservername,
7641                                           r->in.environment,
7642                                           r->in.level,
7643                                           r->out.info,
7644                                           r->out.count);
7645         if (!W_ERROR_IS_OK(result)) {
7646                 return result;
7647         }
7648
7649         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7650                                                      spoolss_EnumPrinterDrivers,
7651                                                      *r->out.info, r->in.level,
7652                                                      *r->out.count);
7653         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7654         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7655
7656         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7657 }
7658
7659 /****************************************************************
7660  _spoolss_EnumForms
7661 ****************************************************************/
7662
7663 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7664                           struct spoolss_EnumForms *r)
7665 {
7666         WERROR result;
7667
7668         *r->out.count = 0;
7669         *r->out.needed = 0;
7670         *r->out.info = NULL;
7671
7672         /* that's an [in out] buffer */
7673
7674         if (!r->in.buffer && (r->in.offered != 0) ) {
7675                 return WERR_INVALID_PARAM;
7676         }
7677
7678         DEBUG(4,("_spoolss_EnumForms\n"));
7679         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7680         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7681
7682         switch (r->in.level) {
7683         case 1:
7684                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7685                                                    get_session_info_system(),
7686                                                    p->msg_ctx,
7687                                                    r->out.count,
7688                                                    r->out.info);
7689                 break;
7690         default:
7691                 result = WERR_UNKNOWN_LEVEL;
7692                 break;
7693         }
7694
7695         if (!W_ERROR_IS_OK(result)) {
7696                 return result;
7697         }
7698
7699         if (*r->out.count == 0) {
7700                 return WERR_NO_MORE_ITEMS;
7701         }
7702
7703         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7704                                                      spoolss_EnumForms,
7705                                                      *r->out.info, r->in.level,
7706                                                      *r->out.count);
7707         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7708         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7709
7710         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7711 }
7712
7713 /****************************************************************
7714  _spoolss_GetForm
7715 ****************************************************************/
7716
7717 WERROR _spoolss_GetForm(struct pipes_struct *p,
7718                         struct spoolss_GetForm *r)
7719 {
7720         WERROR result;
7721
7722         /* that's an [in out] buffer */
7723
7724         if (!r->in.buffer && (r->in.offered != 0)) {
7725                 return WERR_INVALID_PARAM;
7726         }
7727
7728         DEBUG(4,("_spoolss_GetForm\n"));
7729         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7730         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7731
7732         switch (r->in.level) {
7733         case 1:
7734                 result = winreg_printer_getform1_internal(p->mem_ctx,
7735                                                  get_session_info_system(),
7736                                                  p->msg_ctx,
7737                                                  r->in.form_name,
7738                                                  &r->out.info->info1);
7739                 break;
7740         default:
7741                 result = WERR_UNKNOWN_LEVEL;
7742                 break;
7743         }
7744
7745         if (!W_ERROR_IS_OK(result)) {
7746                 TALLOC_FREE(r->out.info);
7747                 return result;
7748         }
7749
7750         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7751                                                r->out.info, r->in.level);
7752         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7753
7754         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7755 }
7756
7757 /****************************************************************************
7758 ****************************************************************************/
7759
7760 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7761                           struct spoolss_PortInfo1 *r,
7762                           const char *name)
7763 {
7764         r->port_name = talloc_strdup(mem_ctx, name);
7765         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7766
7767         return WERR_OK;
7768 }
7769
7770 /****************************************************************************
7771  TODO: This probably needs distinguish between TCP/IP and Local ports
7772  somehow.
7773 ****************************************************************************/
7774
7775 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7776                           struct spoolss_PortInfo2 *r,
7777                           const char *name)
7778 {
7779         r->port_name = talloc_strdup(mem_ctx, name);
7780         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7781
7782         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7783         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7784
7785         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7786         W_ERROR_HAVE_NO_MEMORY(r->description);
7787
7788         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7789         r->reserved = 0;
7790
7791         return WERR_OK;
7792 }
7793
7794
7795 /****************************************************************************
7796  wrapper around the enumer ports command
7797 ****************************************************************************/
7798
7799 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7800 {
7801         char *cmd = lp_enumports_cmd();
7802         char **qlines = NULL;
7803         char *command = NULL;
7804         int numlines;
7805         int ret;
7806         int fd;
7807
7808         *count = 0;
7809         *lines = NULL;
7810
7811         /* if no hook then just fill in the default port */
7812
7813         if ( !*cmd ) {
7814                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7815                         return WERR_NOMEM;
7816                 }
7817                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7818                         TALLOC_FREE(qlines);
7819                         return WERR_NOMEM;
7820                 }
7821                 qlines[1] = NULL;
7822                 numlines = 1;
7823         }
7824         else {
7825                 /* we have a valid enumport command */
7826
7827                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7828                 if (!command) {
7829                         return WERR_NOMEM;
7830                 }
7831
7832                 DEBUG(10,("Running [%s]\n", command));
7833                 ret = smbrun(command, &fd);
7834                 DEBUG(10,("Returned [%d]\n", ret));
7835                 TALLOC_FREE(command);
7836                 if (ret != 0) {
7837                         if (fd != -1) {
7838                                 close(fd);
7839                         }
7840                         return WERR_ACCESS_DENIED;
7841                 }
7842
7843                 numlines = 0;
7844                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7845                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7846                 close(fd);
7847         }
7848
7849         *count = numlines;
7850         *lines = qlines;
7851
7852         return WERR_OK;
7853 }
7854
7855 /****************************************************************************
7856  enumports level 1.
7857 ****************************************************************************/
7858
7859 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7860                                 union spoolss_PortInfo **info_p,
7861                                 uint32_t *count)
7862 {
7863         union spoolss_PortInfo *info = NULL;
7864         int i=0;
7865         WERROR result = WERR_OK;
7866         char **qlines = NULL;
7867         int numlines = 0;
7868
7869         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7870         if (!W_ERROR_IS_OK(result)) {
7871                 goto out;
7872         }
7873
7874         if (numlines) {
7875                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7876                 if (!info) {
7877                         DEBUG(10,("Returning WERR_NOMEM\n"));
7878                         result = WERR_NOMEM;
7879                         goto out;
7880                 }
7881
7882                 for (i=0; i<numlines; i++) {
7883                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7884                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7885                         if (!W_ERROR_IS_OK(result)) {
7886                                 goto out;
7887                         }
7888                 }
7889         }
7890         TALLOC_FREE(qlines);
7891
7892 out:
7893         if (!W_ERROR_IS_OK(result)) {
7894                 TALLOC_FREE(info);
7895                 TALLOC_FREE(qlines);
7896                 *count = 0;
7897                 *info_p = NULL;
7898                 return result;
7899         }
7900
7901         *info_p = info;
7902         *count = numlines;
7903
7904         return WERR_OK;
7905 }
7906
7907 /****************************************************************************
7908  enumports level 2.
7909 ****************************************************************************/
7910
7911 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7912                                 union spoolss_PortInfo **info_p,
7913                                 uint32_t *count)
7914 {
7915         union spoolss_PortInfo *info = NULL;
7916         int i=0;
7917         WERROR result = WERR_OK;
7918         char **qlines = NULL;
7919         int numlines = 0;
7920
7921         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7922         if (!W_ERROR_IS_OK(result)) {
7923                 goto out;
7924         }
7925
7926         if (numlines) {
7927                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7928                 if (!info) {
7929                         DEBUG(10,("Returning WERR_NOMEM\n"));
7930                         result = WERR_NOMEM;
7931                         goto out;
7932                 }
7933
7934                 for (i=0; i<numlines; i++) {
7935                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7936                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7937                         if (!W_ERROR_IS_OK(result)) {
7938                                 goto out;
7939                         }
7940                 }
7941         }
7942         TALLOC_FREE(qlines);
7943
7944 out:
7945         if (!W_ERROR_IS_OK(result)) {
7946                 TALLOC_FREE(info);
7947                 TALLOC_FREE(qlines);
7948                 *count = 0;
7949                 *info_p = NULL;
7950                 return result;
7951         }
7952
7953         *info_p = info;
7954         *count = numlines;
7955
7956         return WERR_OK;
7957 }
7958
7959 /****************************************************************
7960  _spoolss_EnumPorts
7961 ****************************************************************/
7962
7963 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7964                           struct spoolss_EnumPorts *r)
7965 {
7966         WERROR result;
7967
7968         /* that's an [in out] buffer */
7969
7970         if (!r->in.buffer && (r->in.offered != 0)) {
7971                 return WERR_INVALID_PARAM;
7972         }
7973
7974         DEBUG(4,("_spoolss_EnumPorts\n"));
7975
7976         *r->out.count = 0;
7977         *r->out.needed = 0;
7978         *r->out.info = NULL;
7979
7980         switch (r->in.level) {
7981         case 1:
7982                 result = enumports_level_1(p->mem_ctx, r->out.info,
7983                                            r->out.count);
7984                 break;
7985         case 2:
7986                 result = enumports_level_2(p->mem_ctx, r->out.info,
7987                                            r->out.count);
7988                 break;
7989         default:
7990                 return WERR_UNKNOWN_LEVEL;
7991         }
7992
7993         if (!W_ERROR_IS_OK(result)) {
7994                 return result;
7995         }
7996
7997         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7998                                                      spoolss_EnumPorts,
7999                                                      *r->out.info, r->in.level,
8000                                                      *r->out.count);
8001         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8002         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8003
8004         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8005 }
8006
8007 /****************************************************************************
8008 ****************************************************************************/
8009
8010 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8011                                            const char *server,
8012                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8013                                            struct spoolss_DeviceMode *devmode,
8014                                            struct security_descriptor *secdesc,
8015                                            struct spoolss_UserLevelCtr *user_ctr,
8016                                            struct policy_handle *handle)
8017 {
8018         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8019         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8020         int     snum;
8021         WERROR err = WERR_OK;
8022
8023         /* samba does not have a concept of local, non-shared printers yet, so
8024          * make sure we always setup sharename - gd */
8025         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8026             (info2->printername != NULL && info2->printername[0] != '\0')) {
8027                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8028                         "no sharename has been set, setting printername %s as sharename\n",
8029                         info2->printername));
8030                 info2->sharename = info2->printername;
8031         }
8032
8033         /* check to see if the printer already exists */
8034         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8035                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8036                         info2->sharename));
8037                 return WERR_PRINTER_ALREADY_EXISTS;
8038         }
8039
8040         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8041                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8042                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8043                                 info2->printername));
8044                         return WERR_PRINTER_ALREADY_EXISTS;
8045                 }
8046         }
8047
8048         /* validate printer info struct */
8049         if (!info2->printername || strlen(info2->printername) == 0) {
8050                 return WERR_INVALID_PRINTER_NAME;
8051         }
8052         if (!info2->portname || strlen(info2->portname) == 0) {
8053                 return WERR_UNKNOWN_PORT;
8054         }
8055         if (!info2->drivername || strlen(info2->drivername) == 0) {
8056                 return WERR_UNKNOWN_PRINTER_DRIVER;
8057         }
8058         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8059                 return WERR_UNKNOWN_PRINTPROCESSOR;
8060         }
8061
8062         /* FIXME!!!  smbd should check to see if the driver is installed before
8063            trying to add a printer like this  --jerry */
8064
8065         if (*lp_addprinter_cmd() ) {
8066                 char *raddr;
8067
8068                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8069                                                          p->mem_ctx);
8070                 if (raddr == NULL) {
8071                         return WERR_NOMEM;
8072                 }
8073
8074                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8075                                        info2, raddr,
8076                                        p->msg_ctx) ) {
8077                         return WERR_ACCESS_DENIED;
8078                 }
8079         } else {
8080                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8081                         "smb.conf parameter \"addprinter command\" is defined. This "
8082                         "parameter must exist for this call to succeed\n",
8083                         info2->sharename ));
8084         }
8085
8086         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8087                 return WERR_ACCESS_DENIED;
8088         }
8089
8090         /* you must be a printer admin to add a new printer */
8091         if (!print_access_check(p->session_info,
8092                                 p->msg_ctx,
8093                                 snum,
8094                                 PRINTER_ACCESS_ADMINISTER)) {
8095                 return WERR_ACCESS_DENIED;
8096         }
8097
8098         /*
8099          * Do sanity check on the requested changes for Samba.
8100          */
8101
8102         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8103                 return WERR_INVALID_PARAM;
8104         }
8105
8106         if (devmode == NULL) {
8107                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8108         }
8109
8110         err = update_dsspooler(p->mem_ctx,
8111                                get_session_info_system(),
8112                                p->msg_ctx,
8113                                0,
8114                                info2,
8115                                NULL);
8116         if (!W_ERROR_IS_OK(err)) {
8117                 return err;
8118         }
8119
8120         err = winreg_update_printer_internal(p->mem_ctx,
8121                                     get_session_info_system(),
8122                                     p->msg_ctx,
8123                                     info2->sharename,
8124                                     info2_mask,
8125                                     info2,
8126                                     devmode,
8127                                     secdesc);
8128         if (!W_ERROR_IS_OK(err)) {
8129                 return err;
8130         }
8131
8132         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8133         if (!W_ERROR_IS_OK(err)) {
8134                 /* Handle open failed - remove addition. */
8135                 ZERO_STRUCTP(handle);
8136                 return err;
8137         }
8138
8139         return WERR_OK;
8140 }
8141
8142 /****************************************************************
8143  _spoolss_AddPrinterEx
8144 ****************************************************************/
8145
8146 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8147                              struct spoolss_AddPrinterEx *r)
8148 {
8149         switch (r->in.info_ctr->level) {
8150         case 1:
8151                 /* we don't handle yet */
8152                 /* but I know what to do ... */
8153                 return WERR_UNKNOWN_LEVEL;
8154         case 2:
8155                 return spoolss_addprinterex_level_2(p, r->in.server,
8156                                                     r->in.info_ctr,
8157                                                     r->in.devmode_ctr->devmode,
8158                                                     r->in.secdesc_ctr->sd,
8159                                                     r->in.userlevel_ctr,
8160                                                     r->out.handle);
8161         default:
8162                 return WERR_UNKNOWN_LEVEL;
8163         }
8164 }
8165
8166 /****************************************************************
8167  _spoolss_AddPrinter
8168 ****************************************************************/
8169
8170 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8171                            struct spoolss_AddPrinter *r)
8172 {
8173         struct spoolss_AddPrinterEx a;
8174         struct spoolss_UserLevelCtr userlevel_ctr;
8175
8176         ZERO_STRUCT(userlevel_ctr);
8177
8178         userlevel_ctr.level = 1;
8179
8180         a.in.server             = r->in.server;
8181         a.in.info_ctr           = r->in.info_ctr;
8182         a.in.devmode_ctr        = r->in.devmode_ctr;
8183         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8184         a.in.userlevel_ctr      = &userlevel_ctr;
8185         a.out.handle            = r->out.handle;
8186
8187         return _spoolss_AddPrinterEx(p, &a);
8188 }
8189
8190 /****************************************************************
8191  _spoolss_AddPrinterDriverEx
8192 ****************************************************************/
8193
8194 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8195                                    struct spoolss_AddPrinterDriverEx *r)
8196 {
8197         WERROR err = WERR_OK;
8198         const char *driver_name = NULL;
8199         uint32_t version;
8200         const char *fn;
8201
8202         switch (p->opnum) {
8203                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8204                         fn = "_spoolss_AddPrinterDriver";
8205                         break;
8206                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8207                         fn = "_spoolss_AddPrinterDriverEx";
8208                         break;
8209                 default:
8210                         return WERR_INVALID_PARAM;
8211         }
8212
8213         /*
8214          * we only support the semantics of AddPrinterDriver()
8215          * i.e. only copy files that are newer than existing ones
8216          */
8217
8218         if (r->in.flags == 0) {
8219                 return WERR_INVALID_PARAM;
8220         }
8221
8222         if (r->in.flags != APD_COPY_NEW_FILES) {
8223                 return WERR_ACCESS_DENIED;
8224         }
8225
8226         /* FIXME */
8227         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8228                 /* Clever hack from Martin Zielinski <mz@seh.de>
8229                  * to allow downgrade from level 8 (Vista).
8230                  */
8231                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8232                         r->in.info_ctr->level));
8233                 return WERR_UNKNOWN_LEVEL;
8234         }
8235
8236         DEBUG(5,("Cleaning driver's information\n"));
8237         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8238         if (!W_ERROR_IS_OK(err))
8239                 goto done;
8240
8241         DEBUG(5,("Moving driver to final destination\n"));
8242         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8243         if (!W_ERROR_IS_OK(err)) {
8244                 goto done;
8245         }
8246
8247         err = winreg_add_driver_internal(p->mem_ctx,
8248                                 get_session_info_system(),
8249                                 p->msg_ctx,
8250                                 r->in.info_ctr,
8251                                 &driver_name,
8252                                 &version);
8253         if (!W_ERROR_IS_OK(err)) {
8254                 goto done;
8255         }
8256
8257         /*
8258          * I think this is where he DrvUpgradePrinter() hook would be
8259          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8260          * server.  Right now, we just need to send ourselves a message
8261          * to update each printer bound to this driver.   --jerry
8262          */
8263
8264         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8265                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8266                         fn, driver_name));
8267         }
8268
8269 done:
8270         return err;
8271 }
8272
8273 /****************************************************************
8274  _spoolss_AddPrinterDriver
8275 ****************************************************************/
8276
8277 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8278                                  struct spoolss_AddPrinterDriver *r)
8279 {
8280         struct spoolss_AddPrinterDriverEx a;
8281
8282         switch (r->in.info_ctr->level) {
8283         case 2:
8284         case 3:
8285         case 4:
8286         case 5:
8287                 break;
8288         default:
8289                 return WERR_UNKNOWN_LEVEL;
8290         }
8291
8292         a.in.servername         = r->in.servername;
8293         a.in.info_ctr           = r->in.info_ctr;
8294         a.in.flags              = APD_COPY_NEW_FILES;
8295
8296         return _spoolss_AddPrinterDriverEx(p, &a);
8297 }
8298
8299 /****************************************************************************
8300 ****************************************************************************/
8301
8302 struct _spoolss_paths {
8303         int type;
8304         const char *share;
8305         const char *dir;
8306 };
8307
8308 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8309
8310 static const struct _spoolss_paths spoolss_paths[]= {
8311         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8312         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8313 };
8314
8315 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8316                                           const char *servername,
8317                                           const char *environment,
8318                                           int component,
8319                                           char **path)
8320 {
8321         const char *pservername = NULL;
8322         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8323         const char *short_archi;
8324
8325         *path = NULL;
8326
8327         /* environment may be empty */
8328         if (environment && strlen(environment)) {
8329                 long_archi = environment;
8330         }
8331
8332         /* servername may be empty */
8333         if (servername && strlen(servername)) {
8334                 pservername = canon_servername(servername);
8335
8336                 if (!is_myname_or_ipaddr(pservername)) {
8337                         return WERR_INVALID_PARAM;
8338                 }
8339         }
8340
8341         if (!(short_archi = get_short_archi(long_archi))) {
8342                 return WERR_INVALID_ENVIRONMENT;
8343         }
8344
8345         switch (component) {
8346         case SPOOLSS_PRTPROCS_PATH:
8347         case SPOOLSS_DRIVER_PATH:
8348                 if (pservername) {
8349                         *path = talloc_asprintf(mem_ctx,
8350                                         "\\\\%s\\%s\\%s",
8351                                         pservername,
8352                                         spoolss_paths[component].share,
8353                                         short_archi);
8354                 } else {
8355                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8356                                         SPOOLSS_DEFAULT_SERVER_PATH,
8357                                         spoolss_paths[component].dir,
8358                                         short_archi);
8359                 }
8360                 break;
8361         default:
8362                 return WERR_INVALID_PARAM;
8363         }
8364
8365         if (!*path) {
8366                 return WERR_NOMEM;
8367         }
8368
8369         return WERR_OK;
8370 }
8371
8372 /****************************************************************************
8373 ****************************************************************************/
8374
8375 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8376                                           const char *servername,
8377                                           const char *environment,
8378                                           struct spoolss_DriverDirectoryInfo1 *r)
8379 {
8380         WERROR werr;
8381         char *path = NULL;
8382
8383         werr = compose_spoolss_server_path(mem_ctx,
8384                                            servername,
8385                                            environment,
8386                                            SPOOLSS_DRIVER_PATH,
8387                                            &path);
8388         if (!W_ERROR_IS_OK(werr)) {
8389                 return werr;
8390         }
8391
8392         DEBUG(4,("printer driver directory: [%s]\n", path));
8393
8394         r->directory_name = path;
8395
8396         return WERR_OK;
8397 }
8398
8399 /****************************************************************
8400  _spoolss_GetPrinterDriverDirectory
8401 ****************************************************************/
8402
8403 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8404                                           struct spoolss_GetPrinterDriverDirectory *r)
8405 {
8406         WERROR werror;
8407
8408         /* that's an [in out] buffer */
8409
8410         if (!r->in.buffer && (r->in.offered != 0)) {
8411                 return WERR_INVALID_PARAM;
8412         }
8413
8414         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8415                 r->in.level));
8416
8417         *r->out.needed = 0;
8418
8419         /* r->in.level is ignored */
8420
8421         werror = getprinterdriverdir_level_1(p->mem_ctx,
8422                                              r->in.server,
8423                                              r->in.environment,
8424                                              &r->out.info->info1);
8425         if (!W_ERROR_IS_OK(werror)) {
8426                 TALLOC_FREE(r->out.info);
8427                 return werror;
8428         }
8429
8430         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8431                                                r->out.info, r->in.level);
8432         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8433
8434         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8435 }
8436
8437 /****************************************************************
8438  _spoolss_EnumPrinterData
8439 ****************************************************************/
8440
8441 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8442                                 struct spoolss_EnumPrinterData *r)
8443 {
8444         WERROR result;
8445         struct spoolss_EnumPrinterDataEx r2;
8446         uint32_t count;
8447         struct spoolss_PrinterEnumValues *info, *val = NULL;
8448         uint32_t needed;
8449
8450         r2.in.handle    = r->in.handle;
8451         r2.in.key_name  = "PrinterDriverData";
8452         r2.in.offered   = 0;
8453         r2.out.count    = &count;
8454         r2.out.info     = &info;
8455         r2.out.needed   = &needed;
8456
8457         result = _spoolss_EnumPrinterDataEx(p, &r2);
8458         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8459                 r2.in.offered = needed;
8460                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8461         }
8462         if (!W_ERROR_IS_OK(result)) {
8463                 return result;
8464         }
8465
8466         /*
8467          * The NT machine wants to know the biggest size of value and data
8468          *
8469          * cf: MSDN EnumPrinterData remark section
8470          */
8471
8472         if (!r->in.value_offered && !r->in.data_offered) {
8473                 uint32_t biggest_valuesize = 0;
8474                 uint32_t biggest_datasize = 0;
8475                 int i, name_length;
8476
8477                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8478
8479                 for (i=0; i<count; i++) {
8480
8481                         name_length = strlen(info[i].value_name);
8482                         if (strlen(info[i].value_name) > biggest_valuesize) {
8483                                 biggest_valuesize = name_length;
8484                         }
8485
8486                         if (info[i].data_length > biggest_datasize) {
8487                                 biggest_datasize = info[i].data_length;
8488                         }
8489
8490                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8491                                 biggest_datasize));
8492                 }
8493
8494                 /* the value is an UNICODE string but real_value_size is the length
8495                    in bytes including the trailing 0 */
8496
8497                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8498                 *r->out.data_needed  = biggest_datasize;
8499
8500                 DEBUG(6,("final values: [%d], [%d]\n",
8501                         *r->out.value_needed, *r->out.data_needed));
8502
8503                 return WERR_OK;
8504         }
8505
8506         if (r->in.enum_index < count) {
8507                 val = &info[r->in.enum_index];
8508         }
8509
8510         if (val == NULL) {
8511                 /* out_value should default to "" or else NT4 has
8512                    problems unmarshalling the response */
8513
8514                 if (r->in.value_offered) {
8515                         *r->out.value_needed = 1;
8516                         r->out.value_name = talloc_strdup(r, "");
8517                         if (!r->out.value_name) {
8518                                 return WERR_NOMEM;
8519                         }
8520                 } else {
8521                         r->out.value_name = NULL;
8522                         *r->out.value_needed = 0;
8523                 }
8524
8525                 /* the data is counted in bytes */
8526
8527                 *r->out.data_needed = r->in.data_offered;
8528
8529                 result = WERR_NO_MORE_ITEMS;
8530         } else {
8531                 /*
8532                  * the value is:
8533                  * - counted in bytes in the request
8534                  * - counted in UNICODE chars in the max reply
8535                  * - counted in bytes in the real size
8536                  *
8537                  * take a pause *before* coding not *during* coding
8538                  */
8539
8540                 /* name */
8541                 if (r->in.value_offered) {
8542                         r->out.value_name = talloc_strdup(r, val->value_name);
8543                         if (!r->out.value_name) {
8544                                 return WERR_NOMEM;
8545                         }
8546                         *r->out.value_needed = val->value_name_len;
8547                 } else {
8548                         r->out.value_name = NULL;
8549                         *r->out.value_needed = 0;
8550                 }
8551
8552                 /* type */
8553
8554                 *r->out.type = val->type;
8555
8556                 /* data - counted in bytes */
8557
8558                 /*
8559                  * See the section "Dynamically Typed Query Parameters"
8560                  * in MS-RPRN.
8561                  */
8562
8563                 if (r->out.data && val->data && val->data->data &&
8564                                 val->data_length && r->in.data_offered) {
8565                         memcpy(r->out.data, val->data->data,
8566                                 MIN(val->data_length,r->in.data_offered));
8567                 }
8568
8569                 *r->out.data_needed = val->data_length;
8570
8571                 result = WERR_OK;
8572         }
8573
8574         return result;
8575 }
8576
8577 /****************************************************************
8578  _spoolss_SetPrinterData
8579 ****************************************************************/
8580
8581 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8582                                struct spoolss_SetPrinterData *r)
8583 {
8584         struct spoolss_SetPrinterDataEx r2;
8585
8586         r2.in.handle            = r->in.handle;
8587         r2.in.key_name          = "PrinterDriverData";
8588         r2.in.value_name        = r->in.value_name;
8589         r2.in.type              = r->in.type;
8590         r2.in.data              = r->in.data;
8591         r2.in.offered           = r->in.offered;
8592
8593         return _spoolss_SetPrinterDataEx(p, &r2);
8594 }
8595
8596 /****************************************************************
8597  _spoolss_ResetPrinter
8598 ****************************************************************/
8599
8600 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8601                              struct spoolss_ResetPrinter *r)
8602 {
8603         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8604         int             snum;
8605
8606         DEBUG(5,("_spoolss_ResetPrinter\n"));
8607
8608         /*
8609          * All we do is to check to see if the handle and queue is valid.
8610          * This call really doesn't mean anything to us because we only
8611          * support RAW printing.   --jerry
8612          */
8613
8614         if (!Printer) {
8615                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8616                         OUR_HANDLE(r->in.handle)));
8617                 return WERR_BADFID;
8618         }
8619
8620         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8621                 return WERR_BADFID;
8622
8623
8624         /* blindly return success */
8625         return WERR_OK;
8626 }
8627
8628 /****************************************************************
8629  _spoolss_DeletePrinterData
8630 ****************************************************************/
8631
8632 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8633                                   struct spoolss_DeletePrinterData *r)
8634 {
8635         struct spoolss_DeletePrinterDataEx r2;
8636
8637         r2.in.handle            = r->in.handle;
8638         r2.in.key_name          = "PrinterDriverData";
8639         r2.in.value_name        = r->in.value_name;
8640
8641         return _spoolss_DeletePrinterDataEx(p, &r2);
8642 }
8643
8644 /****************************************************************
8645  _spoolss_AddForm
8646 ****************************************************************/
8647
8648 WERROR _spoolss_AddForm(struct pipes_struct *p,
8649                         struct spoolss_AddForm *r)
8650 {
8651         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8652         int snum = -1;
8653         WERROR status = WERR_OK;
8654         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8655         struct dcerpc_binding_handle *b;
8656         TALLOC_CTX *tmp_ctx = NULL;
8657
8658         DEBUG(5,("_spoolss_AddForm\n"));
8659
8660         if (!Printer) {
8661                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8662                         OUR_HANDLE(r->in.handle)));
8663                 return WERR_BADFID;
8664         }
8665
8666         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8667            and not a printer admin, then fail */
8668
8669         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8670             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8671             !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8672                                           p->session_info->info->domain_name,
8673                                           NULL,
8674                                           p->session_info->security_token,
8675                                           lp_printer_admin(snum))) {
8676                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8677                 return WERR_ACCESS_DENIED;
8678         }
8679
8680         switch (form->flags) {
8681         case SPOOLSS_FORM_USER:
8682         case SPOOLSS_FORM_BUILTIN:
8683         case SPOOLSS_FORM_PRINTER:
8684                 break;
8685         default:
8686                 return WERR_INVALID_PARAM;
8687         }
8688
8689         tmp_ctx = talloc_new(p->mem_ctx);
8690         if (!tmp_ctx) {
8691                 return WERR_NOMEM;
8692         }
8693
8694         status = winreg_printer_binding_handle(tmp_ctx,
8695                                                get_session_info_system(),
8696                                                p->msg_ctx,
8697                                                &b);
8698         if (!W_ERROR_IS_OK(status)) {
8699                 goto done;
8700         }
8701
8702         status = winreg_printer_addform1(tmp_ctx, b, form);
8703         if (!W_ERROR_IS_OK(status)) {
8704                 goto done;
8705         }
8706
8707         /*
8708          * ChangeID must always be set if this is a printer
8709          */
8710         if (Printer->printer_type == SPLHND_PRINTER) {
8711                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8712                         status = WERR_BADFID;
8713                         goto done;
8714                 }
8715
8716                 status = winreg_printer_update_changeid(tmp_ctx, b,
8717                                                         lp_const_servicename(snum));
8718         }
8719
8720 done:
8721         talloc_free(tmp_ctx);
8722         return status;
8723 }
8724
8725 /****************************************************************
8726  _spoolss_DeleteForm
8727 ****************************************************************/
8728
8729 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8730                            struct spoolss_DeleteForm *r)
8731 {
8732         const char *form_name = r->in.form_name;
8733         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8734         int snum = -1;
8735         WERROR status = WERR_OK;
8736         struct dcerpc_binding_handle *b;
8737         TALLOC_CTX *tmp_ctx = NULL;
8738
8739         DEBUG(5,("_spoolss_DeleteForm\n"));
8740
8741         if (!Printer) {
8742                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8743                         OUR_HANDLE(r->in.handle)));
8744                 return WERR_BADFID;
8745         }
8746
8747         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8748             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8749             !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8750                                           p->session_info->info->domain_name,
8751                                           NULL,
8752                                           p->session_info->security_token,
8753                                           lp_printer_admin(snum))) {
8754                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8755                 return WERR_ACCESS_DENIED;
8756         }
8757
8758         tmp_ctx = talloc_new(p->mem_ctx);
8759         if (!tmp_ctx) {
8760                 return WERR_NOMEM;
8761         }
8762
8763         status = winreg_printer_binding_handle(tmp_ctx,
8764                                                get_session_info_system(),
8765                                                p->msg_ctx,
8766                                                &b);
8767         if (!W_ERROR_IS_OK(status)) {
8768                 goto done;
8769         }
8770
8771         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8772         if (!W_ERROR_IS_OK(status)) {
8773                 goto done;
8774         }
8775
8776         /*
8777          * ChangeID must always be set if this is a printer
8778          */
8779         if (Printer->printer_type == SPLHND_PRINTER) {
8780                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8781                         status = WERR_BADFID;
8782                         goto done;
8783                 }
8784
8785                 status = winreg_printer_update_changeid(tmp_ctx, b,
8786                                                         lp_const_servicename(snum));
8787         }
8788
8789 done:
8790         talloc_free(tmp_ctx);
8791         return status;
8792 }
8793
8794 /****************************************************************
8795  _spoolss_SetForm
8796 ****************************************************************/
8797
8798 WERROR _spoolss_SetForm(struct pipes_struct *p,
8799                         struct spoolss_SetForm *r)
8800 {
8801         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8802         const char *form_name = r->in.form_name;
8803         int snum = -1;
8804         WERROR status = WERR_OK;
8805         struct dcerpc_binding_handle *b;
8806         TALLOC_CTX *tmp_ctx = NULL;
8807
8808         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8809
8810         DEBUG(5,("_spoolss_SetForm\n"));
8811
8812         if (!Printer) {
8813                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8814                         OUR_HANDLE(r->in.handle)));
8815                 return WERR_BADFID;
8816         }
8817
8818         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8819            and not a printer admin, then fail */
8820
8821         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8822              !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8823              !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8824                                           p->session_info->info->domain_name,
8825                                           NULL,
8826                                           p->session_info->security_token,
8827                                           lp_printer_admin(snum))) {
8828                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8829                 return WERR_ACCESS_DENIED;
8830         }
8831
8832         tmp_ctx = talloc_new(p->mem_ctx);
8833         if (!tmp_ctx) {
8834                 return WERR_NOMEM;
8835         }
8836
8837         status = winreg_printer_binding_handle(tmp_ctx,
8838                                                get_session_info_system(),
8839                                                p->msg_ctx,
8840                                                &b);
8841         if (!W_ERROR_IS_OK(status)) {
8842                 goto done;
8843         }
8844
8845         status = winreg_printer_setform1(tmp_ctx, b,
8846                                          form_name,
8847                                          form);
8848         if (!W_ERROR_IS_OK(status)) {
8849                 goto done;
8850         }
8851
8852         /*
8853          * ChangeID must always be set if this is a printer
8854          */
8855         if (Printer->printer_type == SPLHND_PRINTER) {
8856                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8857                         status = WERR_BADFID;
8858                         goto done;
8859                 }
8860
8861                 status = winreg_printer_update_changeid(tmp_ctx, b,
8862                                                         lp_const_servicename(snum));
8863         }
8864
8865 done:
8866         talloc_free(tmp_ctx);
8867         return status;
8868 }
8869
8870 /****************************************************************************
8871  fill_print_processor1
8872 ****************************************************************************/
8873
8874 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8875                                     struct spoolss_PrintProcessorInfo1 *r,
8876                                     const char *print_processor_name)
8877 {
8878         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8879         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8880
8881         return WERR_OK;
8882 }
8883
8884 /****************************************************************************
8885  enumprintprocessors level 1.
8886 ****************************************************************************/
8887
8888 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8889                                           union spoolss_PrintProcessorInfo **info_p,
8890                                           uint32_t *count)
8891 {
8892         union spoolss_PrintProcessorInfo *info;
8893         WERROR result;
8894
8895         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8896         W_ERROR_HAVE_NO_MEMORY(info);
8897
8898         *count = 1;
8899
8900         result = fill_print_processor1(info, &info[0].info1, "winprint");
8901         if (!W_ERROR_IS_OK(result)) {
8902                 goto out;
8903         }
8904
8905  out:
8906         if (!W_ERROR_IS_OK(result)) {
8907                 TALLOC_FREE(info);
8908                 *count = 0;
8909                 return result;
8910         }
8911
8912         *info_p = info;
8913
8914         return WERR_OK;
8915 }
8916
8917 /****************************************************************
8918  _spoolss_EnumPrintProcessors
8919 ****************************************************************/
8920
8921 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8922                                     struct spoolss_EnumPrintProcessors *r)
8923 {
8924         WERROR result;
8925
8926         /* that's an [in out] buffer */
8927
8928         if (!r->in.buffer && (r->in.offered != 0)) {
8929                 return WERR_INVALID_PARAM;
8930         }
8931
8932         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8933
8934         /*
8935          * Enumerate the print processors ...
8936          *
8937          * Just reply with "winprint", to keep NT happy
8938          * and I can use my nice printer checker.
8939          */
8940
8941         *r->out.count = 0;
8942         *r->out.needed = 0;
8943         *r->out.info = NULL;
8944
8945         if (!get_short_archi(r->in.environment)) {
8946                 return WERR_INVALID_ENVIRONMENT;
8947         }
8948
8949         switch (r->in.level) {
8950         case 1:
8951                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8952                                                      r->out.count);
8953                 break;
8954         default:
8955                 return WERR_UNKNOWN_LEVEL;
8956         }
8957
8958         if (!W_ERROR_IS_OK(result)) {
8959                 return result;
8960         }
8961
8962         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8963                                                      spoolss_EnumPrintProcessors,
8964                                                      *r->out.info, r->in.level,
8965                                                      *r->out.count);
8966         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8967         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8968
8969         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8970 }
8971
8972 /****************************************************************************
8973  fill_printprocdatatype1
8974 ****************************************************************************/
8975
8976 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8977                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8978                                       const char *name_array)
8979 {
8980         r->name_array = talloc_strdup(mem_ctx, name_array);
8981         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8982
8983         return WERR_OK;
8984 }
8985
8986 /****************************************************************************
8987  enumprintprocdatatypes level 1.
8988 ****************************************************************************/
8989
8990 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8991                                              union spoolss_PrintProcDataTypesInfo **info_p,
8992                                              uint32_t *count)
8993 {
8994         WERROR result;
8995         union spoolss_PrintProcDataTypesInfo *info;
8996
8997         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8998         W_ERROR_HAVE_NO_MEMORY(info);
8999
9000         *count = 1;
9001
9002         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9003         if (!W_ERROR_IS_OK(result)) {
9004                 goto out;
9005         }
9006
9007  out:
9008         if (!W_ERROR_IS_OK(result)) {
9009                 TALLOC_FREE(info);
9010                 *count = 0;
9011                 return result;
9012         }
9013
9014         *info_p = info;
9015
9016         return WERR_OK;
9017 }
9018
9019 /****************************************************************
9020  _spoolss_EnumPrintProcDataTypes
9021 ****************************************************************/
9022
9023 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9024                                        struct spoolss_EnumPrintProcDataTypes *r)
9025 {
9026         WERROR result;
9027
9028         /* that's an [in out] buffer */
9029
9030         if (!r->in.buffer && (r->in.offered != 0)) {
9031                 return WERR_INVALID_PARAM;
9032         }
9033
9034         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9035
9036         *r->out.count = 0;
9037         *r->out.needed = 0;
9038         *r->out.info = NULL;
9039
9040         if (r->in.print_processor_name == NULL ||
9041             !strequal(r->in.print_processor_name, "winprint")) {
9042                 return WERR_UNKNOWN_PRINTPROCESSOR;
9043         }
9044
9045         switch (r->in.level) {
9046         case 1:
9047                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9048                                                         r->out.count);
9049                 break;
9050         default:
9051                 return WERR_UNKNOWN_LEVEL;
9052         }
9053
9054         if (!W_ERROR_IS_OK(result)) {
9055                 return result;
9056         }
9057
9058         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9059                                                      spoolss_EnumPrintProcDataTypes,
9060                                                      *r->out.info, r->in.level,
9061                                                      *r->out.count);
9062         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9063         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9064
9065         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9066 }
9067
9068 /****************************************************************************
9069  fill_monitor_1
9070 ****************************************************************************/
9071
9072 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9073                              struct spoolss_MonitorInfo1 *r,
9074                              const char *monitor_name)
9075 {
9076         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9077         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9078
9079         return WERR_OK;
9080 }
9081
9082 /****************************************************************************
9083  fill_monitor_2
9084 ****************************************************************************/
9085
9086 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9087                              struct spoolss_MonitorInfo2 *r,
9088                              const char *monitor_name,
9089                              const char *environment,
9090                              const char *dll_name)
9091 {
9092         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9093         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9094         r->environment                  = talloc_strdup(mem_ctx, environment);
9095         W_ERROR_HAVE_NO_MEMORY(r->environment);
9096         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9097         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9098
9099         return WERR_OK;
9100 }
9101
9102 /****************************************************************************
9103  enumprintmonitors level 1.
9104 ****************************************************************************/
9105
9106 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9107                                         union spoolss_MonitorInfo **info_p,
9108                                         uint32_t *count)
9109 {
9110         union spoolss_MonitorInfo *info;
9111         WERROR result = WERR_OK;
9112
9113         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9114         W_ERROR_HAVE_NO_MEMORY(info);
9115
9116         *count = 2;
9117
9118         result = fill_monitor_1(info, &info[0].info1,
9119                                 SPL_LOCAL_PORT);
9120         if (!W_ERROR_IS_OK(result)) {
9121                 goto out;
9122         }
9123
9124         result = fill_monitor_1(info, &info[1].info1,
9125                                 SPL_TCPIP_PORT);
9126         if (!W_ERROR_IS_OK(result)) {
9127                 goto out;
9128         }
9129
9130 out:
9131         if (!W_ERROR_IS_OK(result)) {
9132                 TALLOC_FREE(info);
9133                 *count = 0;
9134                 return result;
9135         }
9136
9137         *info_p = info;
9138
9139         return WERR_OK;
9140 }
9141
9142 /****************************************************************************
9143  enumprintmonitors level 2.
9144 ****************************************************************************/
9145
9146 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9147                                         union spoolss_MonitorInfo **info_p,
9148                                         uint32_t *count)
9149 {
9150         union spoolss_MonitorInfo *info;
9151         WERROR result = WERR_OK;
9152
9153         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9154         W_ERROR_HAVE_NO_MEMORY(info);
9155
9156         *count = 2;
9157
9158         result = fill_monitor_2(info, &info[0].info2,
9159                                 SPL_LOCAL_PORT,
9160                                 "Windows NT X86", /* FIXME */
9161                                 "localmon.dll");
9162         if (!W_ERROR_IS_OK(result)) {
9163                 goto out;
9164         }
9165
9166         result = fill_monitor_2(info, &info[1].info2,
9167                                 SPL_TCPIP_PORT,
9168                                 "Windows NT X86", /* FIXME */
9169                                 "tcpmon.dll");
9170         if (!W_ERROR_IS_OK(result)) {
9171                 goto out;
9172         }
9173
9174 out:
9175         if (!W_ERROR_IS_OK(result)) {
9176                 TALLOC_FREE(info);
9177                 *count = 0;
9178                 return result;
9179         }
9180
9181         *info_p = info;
9182
9183         return WERR_OK;
9184 }
9185
9186 /****************************************************************
9187  _spoolss_EnumMonitors
9188 ****************************************************************/
9189
9190 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9191                              struct spoolss_EnumMonitors *r)
9192 {
9193         WERROR result;
9194
9195         /* that's an [in out] buffer */
9196
9197         if (!r->in.buffer && (r->in.offered != 0)) {
9198                 return WERR_INVALID_PARAM;
9199         }
9200
9201         DEBUG(5,("_spoolss_EnumMonitors\n"));
9202
9203         /*
9204          * Enumerate the print monitors ...
9205          *
9206          * Just reply with "Local Port", to keep NT happy
9207          * and I can use my nice printer checker.
9208          */
9209
9210         *r->out.count = 0;
9211         *r->out.needed = 0;
9212         *r->out.info = NULL;
9213
9214         switch (r->in.level) {
9215         case 1:
9216                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9217                                                    r->out.count);
9218                 break;
9219         case 2:
9220                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9221                                                    r->out.count);
9222                 break;
9223         default:
9224                 return WERR_UNKNOWN_LEVEL;
9225         }
9226
9227         if (!W_ERROR_IS_OK(result)) {
9228                 return result;
9229         }
9230
9231         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9232                                                      spoolss_EnumMonitors,
9233                                                      *r->out.info, r->in.level,
9234                                                      *r->out.count);
9235         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9236         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9237
9238         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9239 }
9240
9241 /****************************************************************************
9242 ****************************************************************************/
9243
9244 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9245                              const print_queue_struct *queue,
9246                              int count, int snum,
9247                              struct spoolss_PrinterInfo2 *pinfo2,
9248                              uint32_t jobid,
9249                              struct spoolss_JobInfo1 *r)
9250 {
9251         int i = 0;
9252         bool found = false;
9253
9254         for (i=0; i<count; i++) {
9255                 if (queue[i].job == (int)jobid) {
9256                         found = true;
9257                         break;
9258                 }
9259         }
9260
9261         if (found == false) {
9262                 /* NT treats not found as bad param... yet another bad choice */
9263                 return WERR_INVALID_PARAM;
9264         }
9265
9266         return fill_job_info1(mem_ctx,
9267                               r,
9268                               &queue[i],
9269                               i,
9270                               snum,
9271                               pinfo2);
9272 }
9273
9274 /****************************************************************************
9275 ****************************************************************************/
9276
9277 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9278                              const print_queue_struct *queue,
9279                              int count, int snum,
9280                              struct spoolss_PrinterInfo2 *pinfo2,
9281                              uint32_t jobid,
9282                              struct spoolss_JobInfo2 *r)
9283 {
9284         int i = 0;
9285         bool found = false;
9286         struct spoolss_DeviceMode *devmode;
9287         WERROR result;
9288
9289         for (i=0; i<count; i++) {
9290                 if (queue[i].job == (int)jobid) {
9291                         found = true;
9292                         break;
9293                 }
9294         }
9295
9296         if (found == false) {
9297                 /* NT treats not found as bad param... yet another bad
9298                    choice */
9299                 return WERR_INVALID_PARAM;
9300         }
9301
9302         /*
9303          * if the print job does not have a DEVMODE associated with it,
9304          * just use the one for the printer. A NULL devicemode is not
9305          *  a failure condition
9306          */
9307
9308         devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9309         if (!devmode) {
9310                 result = spoolss_create_default_devmode(mem_ctx,
9311                                                 pinfo2->printername,
9312                                                 &devmode);
9313                 if (!W_ERROR_IS_OK(result)) {
9314                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9315                         return result;
9316                 }
9317         }
9318
9319         return fill_job_info2(mem_ctx,
9320                               r,
9321                               &queue[i],
9322                               i,
9323                               snum,
9324                               pinfo2,
9325                               devmode);
9326 }
9327
9328 /****************************************************************
9329  _spoolss_GetJob
9330 ****************************************************************/
9331
9332 WERROR _spoolss_GetJob(struct pipes_struct *p,
9333                        struct spoolss_GetJob *r)
9334 {
9335         WERROR result = WERR_OK;
9336         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9337         int snum;
9338         int count;
9339         print_queue_struct      *queue = NULL;
9340         print_status_struct prt_status;
9341
9342         /* that's an [in out] buffer */
9343
9344         if (!r->in.buffer && (r->in.offered != 0)) {
9345                 return WERR_INVALID_PARAM;
9346         }
9347
9348         DEBUG(5,("_spoolss_GetJob\n"));
9349
9350         *r->out.needed = 0;
9351
9352         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9353                 return WERR_BADFID;
9354         }
9355
9356         result = winreg_get_printer_internal(p->mem_ctx,
9357                                     get_session_info_system(),
9358                                     p->msg_ctx,
9359                                     lp_const_servicename(snum),
9360                                     &pinfo2);
9361         if (!W_ERROR_IS_OK(result)) {
9362                 return result;
9363         }
9364
9365         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9366
9367         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9368                      count, prt_status.status, prt_status.message));
9369
9370         switch (r->in.level) {
9371         case 1:
9372                 result = getjob_level_1(p->mem_ctx,
9373                                         queue, count, snum, pinfo2,
9374                                         r->in.job_id, &r->out.info->info1);
9375                 break;
9376         case 2:
9377                 result = getjob_level_2(p->mem_ctx,
9378                                         queue, count, snum, pinfo2,
9379                                         r->in.job_id, &r->out.info->info2);
9380                 break;
9381         default:
9382                 result = WERR_UNKNOWN_LEVEL;
9383                 break;
9384         }
9385
9386         SAFE_FREE(queue);
9387         TALLOC_FREE(pinfo2);
9388
9389         if (!W_ERROR_IS_OK(result)) {
9390                 TALLOC_FREE(r->out.info);
9391                 return result;
9392         }
9393
9394         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9395                                                                                    r->in.level);
9396         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9397
9398         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9399 }
9400
9401 /****************************************************************
9402  _spoolss_GetPrinterDataEx
9403 ****************************************************************/
9404
9405 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9406                                  struct spoolss_GetPrinterDataEx *r)
9407 {
9408
9409         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9410         const char *printer;
9411         int                     snum = 0;
9412         WERROR result = WERR_OK;
9413         DATA_BLOB blob;
9414         enum winreg_Type val_type = REG_NONE;
9415         uint8_t *val_data = NULL;
9416         uint32_t val_size = 0;
9417         struct dcerpc_binding_handle *b;
9418         TALLOC_CTX *tmp_ctx;
9419
9420         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9421
9422         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9423                 r->in.key_name, r->in.value_name));
9424
9425         /* in case of problem, return some default values */
9426
9427         *r->out.needed  = 0;
9428         *r->out.type    = REG_NONE;
9429
9430         tmp_ctx = talloc_new(p->mem_ctx);
9431         if (!tmp_ctx) {
9432                 return WERR_NOMEM;
9433         }
9434
9435         if (!Printer) {
9436                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9437                         OUR_HANDLE(r->in.handle)));
9438                 result = WERR_BADFID;
9439                 goto done;
9440         }
9441
9442         /* check to see if the keyname is valid */
9443         if (!strlen(r->in.key_name)) {
9444                 result = WERR_INVALID_PARAM;
9445                 goto done;
9446         }
9447
9448         /* Is the handle to a printer or to the server? */
9449
9450         if (Printer->printer_type == SPLHND_SERVER) {
9451
9452                 union spoolss_PrinterData data;
9453
9454                 result = getprinterdata_printer_server(tmp_ctx,
9455                                                        r->in.value_name,
9456                                                        r->out.type,
9457                                                        &data);
9458                 if (!W_ERROR_IS_OK(result)) {
9459                         goto done;
9460                 }
9461
9462                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9463                                                   *r->out.type, &data);
9464                 if (!W_ERROR_IS_OK(result)) {
9465                         goto done;
9466                 }
9467
9468                 *r->out.needed = blob.length;
9469
9470                 if (r->in.offered >= *r->out.needed) {
9471                         memcpy(r->out.data, blob.data, blob.length);
9472                 }
9473
9474                 result = WERR_OK;
9475                 goto done;
9476         }
9477
9478         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9479                 result = WERR_BADFID;
9480                 goto done;
9481         }
9482         printer = lp_const_servicename(snum);
9483
9484         result = winreg_printer_binding_handle(tmp_ctx,
9485                                                get_session_info_system(),
9486                                                p->msg_ctx,
9487                                                &b);
9488         if (!W_ERROR_IS_OK(result)) {
9489                 goto done;
9490         }
9491
9492         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9493         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9494             strequal(r->in.value_name, "ChangeId")) {
9495                 *r->out.type = REG_DWORD;
9496                 *r->out.needed = 4;
9497                 if (r->in.offered >= *r->out.needed) {
9498                         uint32_t changeid = 0;
9499
9500                         result = winreg_printer_get_changeid(tmp_ctx, b,
9501                                                              printer,
9502                                                              &changeid);
9503                         if (!W_ERROR_IS_OK(result)) {
9504                                 goto done;
9505                         }
9506
9507                         SIVAL(r->out.data, 0, changeid);
9508                         result = WERR_OK;
9509                 }
9510                 goto done;
9511         }
9512
9513         result = winreg_get_printer_dataex(tmp_ctx, b,
9514                                            printer,
9515                                            r->in.key_name,
9516                                            r->in.value_name,
9517                                            &val_type,
9518                                            &val_data,
9519                                            &val_size);
9520         if (!W_ERROR_IS_OK(result)) {
9521                 goto done;
9522         }
9523
9524         *r->out.needed = val_size;
9525         *r->out.type = val_type;
9526
9527         if (r->in.offered >= *r->out.needed) {
9528                 memcpy(r->out.data, val_data, val_size);
9529         }
9530
9531 done:
9532         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9533
9534         if (W_ERROR_IS_OK(result)) {
9535                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9536         }
9537
9538         talloc_free(tmp_ctx);
9539         return result;
9540 }
9541
9542 /****************************************************************
9543  _spoolss_SetPrinterDataEx
9544 ****************************************************************/
9545
9546 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9547                                  struct spoolss_SetPrinterDataEx *r)
9548 {
9549         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9550         int                     snum = 0;
9551         WERROR                  result = WERR_OK;
9552         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9553         char                    *oid_string;
9554         struct dcerpc_binding_handle *b;
9555         TALLOC_CTX *tmp_ctx;
9556
9557         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9558
9559         /* From MSDN documentation of SetPrinterDataEx: pass request to
9560            SetPrinterData if key is "PrinterDriverData" */
9561
9562         if (!Printer) {
9563                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9564                         OUR_HANDLE(r->in.handle)));
9565                 return WERR_BADFID;
9566         }
9567
9568         if (Printer->printer_type == SPLHND_SERVER) {
9569                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9570                         "Not implemented for server handles yet\n"));
9571                 return WERR_INVALID_PARAM;
9572         }
9573
9574         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9575                 return WERR_BADFID;
9576         }
9577
9578         /*
9579          * Access check : NT returns "access denied" if you make a
9580          * SetPrinterData call without the necessary privildge.
9581          * we were originally returning OK if nothing changed
9582          * which made Win2k issue **a lot** of SetPrinterData
9583          * when connecting to a printer  --jerry
9584          */
9585
9586         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9587                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9588                         "change denied by handle access permissions\n"));
9589                 return WERR_ACCESS_DENIED;
9590         }
9591
9592         tmp_ctx = talloc_new(p->mem_ctx);
9593         if (!tmp_ctx) {
9594                 return WERR_NOMEM;
9595         }
9596
9597         result = winreg_printer_binding_handle(tmp_ctx,
9598                                                get_session_info_system(),
9599                                                p->msg_ctx,
9600                                                &b);
9601         if (!W_ERROR_IS_OK(result)) {
9602                 goto done;
9603         }
9604
9605         result = winreg_get_printer(tmp_ctx, b,
9606                                     lp_servicename(snum),
9607                                     &pinfo2);
9608         if (!W_ERROR_IS_OK(result)) {
9609                 goto done;
9610         }
9611
9612         /* check for OID in valuename */
9613
9614         oid_string = strchr(r->in.value_name, ',');
9615         if (oid_string) {
9616                 *oid_string = '\0';
9617                 oid_string++;
9618         }
9619
9620         /* save the registry data */
9621
9622         result = winreg_set_printer_dataex(tmp_ctx, b,
9623                                            pinfo2->sharename,
9624                                            r->in.key_name,
9625                                            r->in.value_name,
9626                                            r->in.type,
9627                                            r->in.data,
9628                                            r->in.offered);
9629
9630         if (W_ERROR_IS_OK(result)) {
9631                 /* save the OID if one was specified */
9632                 if (oid_string) {
9633                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9634                                 r->in.key_name, SPOOL_OID_KEY);
9635                         if (!str) {
9636                                 result = WERR_NOMEM;
9637                                 goto done;
9638                         }
9639
9640                         /*
9641                          * I'm not checking the status here on purpose.  Don't know
9642                          * if this is right, but I'm returning the status from the
9643                          * previous set_printer_dataex() call.  I have no idea if
9644                          * this is right.    --jerry
9645                          */
9646                         winreg_set_printer_dataex(tmp_ctx, b,
9647                                                   pinfo2->sharename,
9648                                                   str,
9649                                                   r->in.value_name,
9650                                                   REG_SZ,
9651                                                   (uint8_t *) oid_string,
9652                                                   strlen(oid_string) + 1);
9653                 }
9654
9655                 result = winreg_printer_update_changeid(tmp_ctx, b,
9656                                                         lp_const_servicename(snum));
9657
9658         }
9659
9660 done:
9661         talloc_free(tmp_ctx);
9662         return result;
9663 }
9664
9665 /****************************************************************
9666  _spoolss_DeletePrinterDataEx
9667 ****************************************************************/
9668
9669 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9670                                     struct spoolss_DeletePrinterDataEx *r)
9671 {
9672         const char *printer;
9673         int             snum=0;
9674         WERROR          status = WERR_OK;
9675         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9676
9677         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9678
9679         if (!Printer) {
9680                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9681                         "Invalid handle (%s:%u:%u).\n",
9682                         OUR_HANDLE(r->in.handle)));
9683                 return WERR_BADFID;
9684         }
9685
9686         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9687                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9688                         "printer properties change denied by handle\n"));
9689                 return WERR_ACCESS_DENIED;
9690         }
9691
9692         if (!r->in.value_name || !r->in.key_name) {
9693                 return WERR_NOMEM;
9694         }
9695
9696         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9697                 return WERR_BADFID;
9698         }
9699         printer = lp_const_servicename(snum);
9700
9701         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9702                                               get_session_info_system(),
9703                                               p->msg_ctx,
9704                                               printer,
9705                                               r->in.key_name,
9706                                               r->in.value_name);
9707         if (W_ERROR_IS_OK(status)) {
9708                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9709                                                         get_session_info_system(),
9710                                                         p->msg_ctx,
9711                                                         printer);
9712         }
9713
9714         return status;
9715 }
9716
9717 /****************************************************************
9718  _spoolss_EnumPrinterKey
9719 ****************************************************************/
9720
9721 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9722                                struct spoolss_EnumPrinterKey *r)
9723 {
9724         uint32_t        num_keys;
9725         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9726         int             snum = 0;
9727         WERROR          result = WERR_BADFILE;
9728         const char **array = NULL;
9729         DATA_BLOB blob;
9730
9731         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9732
9733         if (!Printer) {
9734                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9735                         OUR_HANDLE(r->in.handle)));
9736                 return WERR_BADFID;
9737         }
9738
9739         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9740                 return WERR_BADFID;
9741         }
9742
9743         result = winreg_enum_printer_key_internal(p->mem_ctx,
9744                                          get_session_info_system(),
9745                                          p->msg_ctx,
9746                                          lp_const_servicename(snum),
9747                                          r->in.key_name,
9748                                          &num_keys,
9749                                          &array);
9750         if (!W_ERROR_IS_OK(result)) {
9751                 goto done;
9752         }
9753
9754         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9755                 result = WERR_NOMEM;
9756                 goto done;
9757         }
9758
9759         *r->out._ndr_size = r->in.offered / 2;
9760         *r->out.needed = blob.length;
9761
9762         if (r->in.offered < *r->out.needed) {
9763                 result = WERR_MORE_DATA;
9764         } else {
9765                 result = WERR_OK;
9766                 r->out.key_buffer->string_array = array;
9767         }
9768
9769  done:
9770         if (!W_ERROR_IS_OK(result)) {
9771                 TALLOC_FREE(array);
9772                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9773                         *r->out.needed = 0;
9774                 }
9775         }
9776
9777         return result;
9778 }
9779
9780 /****************************************************************
9781  _spoolss_DeletePrinterKey
9782 ****************************************************************/
9783
9784 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9785                                  struct spoolss_DeletePrinterKey *r)
9786 {
9787         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9788         int                     snum=0;
9789         WERROR                  status;
9790         const char *printer;
9791         struct dcerpc_binding_handle *b;
9792         TALLOC_CTX *tmp_ctx;
9793
9794         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9795
9796         if (!Printer) {
9797                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9798                         OUR_HANDLE(r->in.handle)));
9799                 return WERR_BADFID;
9800         }
9801
9802         /* if keyname == NULL, return error */
9803         if ( !r->in.key_name )
9804                 return WERR_INVALID_PARAM;
9805
9806         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9807                 return WERR_BADFID;
9808         }
9809
9810         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9811                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9812                         "printer properties change denied by handle\n"));
9813                 return WERR_ACCESS_DENIED;
9814         }
9815
9816         printer = lp_const_servicename(snum);
9817
9818         tmp_ctx = talloc_new(p->mem_ctx);
9819         if (!tmp_ctx) {
9820                 return WERR_NOMEM;
9821         }
9822
9823         status = winreg_printer_binding_handle(tmp_ctx,
9824                                                get_session_info_system(),
9825                                                p->msg_ctx,
9826                                                &b);
9827         if (!W_ERROR_IS_OK(status)) {
9828                 goto done;
9829         }
9830
9831         /* delete the key and all subkeys */
9832         status = winreg_delete_printer_key(tmp_ctx, b,
9833                                            printer,
9834                                            r->in.key_name);
9835         if (W_ERROR_IS_OK(status)) {
9836                 status = winreg_printer_update_changeid(tmp_ctx, b,
9837                                                         printer);
9838         }
9839
9840 done:
9841         talloc_free(tmp_ctx);
9842         return status;
9843 }
9844
9845 /****************************************************************
9846  _spoolss_EnumPrinterDataEx
9847 ****************************************************************/
9848
9849 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9850                                   struct spoolss_EnumPrinterDataEx *r)
9851 {
9852         uint32_t        count = 0;
9853         struct spoolss_PrinterEnumValues *info = NULL;
9854         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9855         int             snum;
9856         WERROR          result;
9857
9858         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9859
9860         *r->out.count = 0;
9861         *r->out.needed = 0;
9862         *r->out.info = NULL;
9863
9864         if (!Printer) {
9865                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9866                         OUR_HANDLE(r->in.handle)));
9867                 return WERR_BADFID;
9868         }
9869
9870         /*
9871          * first check for a keyname of NULL or "".  Win2k seems to send
9872          * this a lot and we should send back WERR_INVALID_PARAM
9873          * no need to spend time looking up the printer in this case.
9874          * --jerry
9875          */
9876
9877         if (!strlen(r->in.key_name)) {
9878                 result = WERR_INVALID_PARAM;
9879                 goto done;
9880         }
9881
9882         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9883                 return WERR_BADFID;
9884         }
9885
9886         /* now look for a match on the key name */
9887         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9888                                             get_session_info_system(),
9889                                             p->msg_ctx,
9890                                             lp_const_servicename(snum),
9891                                             r->in.key_name,
9892                                             &count,
9893                                             &info);
9894         if (!W_ERROR_IS_OK(result)) {
9895                 goto done;
9896         }
9897
9898 #if 0 /* FIXME - gd */
9899         /* housekeeping information in the reply */
9900
9901         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9902          * the hand marshalled container size is a multiple
9903          * of 4 bytes for RPC alignment.
9904          */
9905
9906         if (needed % 4) {
9907                 needed += 4-(needed % 4);
9908         }
9909 #endif
9910         *r->out.count   = count;
9911         *r->out.info    = info;
9912
9913  done:
9914         if (!W_ERROR_IS_OK(result)) {
9915                 return result;
9916         }
9917
9918         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9919                                                spoolss_EnumPrinterDataEx,
9920                                                *r->out.info,
9921                                                *r->out.count);
9922         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9923         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9924
9925         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9926 }
9927
9928 /****************************************************************************
9929 ****************************************************************************/
9930
9931 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9932                                                  const char *servername,
9933                                                  const char *environment,
9934                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9935 {
9936         WERROR werr;
9937         char *path = NULL;
9938
9939         werr = compose_spoolss_server_path(mem_ctx,
9940                                            servername,
9941                                            environment,
9942                                            SPOOLSS_PRTPROCS_PATH,
9943                                            &path);
9944         if (!W_ERROR_IS_OK(werr)) {
9945                 return werr;
9946         }
9947
9948         DEBUG(4,("print processor directory: [%s]\n", path));
9949
9950         r->directory_name = path;
9951
9952         return WERR_OK;
9953 }
9954
9955 /****************************************************************
9956  _spoolss_GetPrintProcessorDirectory
9957 ****************************************************************/
9958
9959 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9960                                            struct spoolss_GetPrintProcessorDirectory *r)
9961 {
9962         WERROR result;
9963         char *prnproc_share = NULL;
9964         bool prnproc_share_exists = false;
9965         int snum;
9966
9967         /* that's an [in out] buffer */
9968
9969         if (!r->in.buffer && (r->in.offered != 0)) {
9970                 return WERR_INVALID_PARAM;
9971         }
9972
9973         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9974                 r->in.level));
9975
9976         *r->out.needed = 0;
9977
9978         /* r->in.level is ignored */
9979
9980         /* We always should reply with a local print processor directory so that
9981          * users are not forced to have a [prnproc$] share on the Samba spoolss
9982          * server, if users decide to do so, lets announce it though - Guenther */
9983
9984         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9985         if (!prnproc_share) {
9986                 return WERR_NOMEM;
9987         }
9988         if (snum != -1) {
9989                 prnproc_share_exists = true;
9990         }
9991
9992         result = getprintprocessordirectory_level_1(p->mem_ctx,
9993                                                     prnproc_share_exists ? r->in.server : NULL,
9994                                                     r->in.environment,
9995                                                     &r->out.info->info1);
9996         if (!W_ERROR_IS_OK(result)) {
9997                 TALLOC_FREE(r->out.info);
9998                 return result;
9999         }
10000
10001         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10002                                                                                    r->out.info, r->in.level);
10003         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10004
10005         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10006 }
10007
10008 /*******************************************************************
10009  ********************************************************************/
10010
10011 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10012                                const char *dllname)
10013 {
10014         enum ndr_err_code ndr_err;
10015         struct spoolss_MonitorUi ui;
10016
10017         ui.dll_name = dllname;
10018
10019         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10020                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10021         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10022                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10023         }
10024         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10025 }
10026
10027 /*******************************************************************
10028  Streams the monitor UI DLL name in UNICODE
10029 *******************************************************************/
10030
10031 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10032                                struct security_token *token, DATA_BLOB *in,
10033                                DATA_BLOB *out, uint32_t *needed)
10034 {
10035         const char *dllname = "tcpmonui.dll";
10036
10037         *needed = (strlen(dllname)+1) * 2;
10038
10039         if (out->length < *needed) {
10040                 return WERR_INSUFFICIENT_BUFFER;
10041         }
10042
10043         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10044                 return WERR_NOMEM;
10045         }
10046
10047         return WERR_OK;
10048 }
10049
10050 /*******************************************************************
10051  ********************************************************************/
10052
10053 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10054                              struct spoolss_PortData1 *port1,
10055                              const DATA_BLOB *buf)
10056 {
10057         enum ndr_err_code ndr_err;
10058         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10059                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10060         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10061                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10062         }
10063         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10064 }
10065
10066 /*******************************************************************
10067  ********************************************************************/
10068
10069 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10070                              struct spoolss_PortData2 *port2,
10071                              const DATA_BLOB *buf)
10072 {
10073         enum ndr_err_code ndr_err;
10074         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10075                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10076         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10077                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10078         }
10079         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10080 }
10081
10082 /*******************************************************************
10083  Create a new TCP/IP port
10084 *******************************************************************/
10085
10086 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10087                              struct security_token *token, DATA_BLOB *in,
10088                              DATA_BLOB *out, uint32_t *needed)
10089 {
10090         struct spoolss_PortData1 port1;
10091         struct spoolss_PortData2 port2;
10092         char *device_uri = NULL;
10093         uint32_t version;
10094
10095         const char *portname;
10096         const char *hostaddress;
10097         const char *queue;
10098         uint32_t port_number;
10099         uint32_t protocol;
10100
10101         /* peek for spoolss_PortData version */
10102
10103         if (!in || (in->length < (128 + 4))) {
10104                 return WERR_GENERAL_FAILURE;
10105         }
10106
10107         version = IVAL(in->data, 128);
10108
10109         switch (version) {
10110                 case 1:
10111                         ZERO_STRUCT(port1);
10112
10113                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10114                                 return WERR_NOMEM;
10115                         }
10116
10117                         portname        = port1.portname;
10118                         hostaddress     = port1.hostaddress;
10119                         queue           = port1.queue;
10120                         protocol        = port1.protocol;
10121                         port_number     = port1.port_number;
10122
10123                         break;
10124                 case 2:
10125                         ZERO_STRUCT(port2);
10126
10127                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10128                                 return WERR_NOMEM;
10129                         }
10130
10131                         portname        = port2.portname;
10132                         hostaddress     = port2.hostaddress;
10133                         queue           = port2.queue;
10134                         protocol        = port2.protocol;
10135                         port_number     = port2.port_number;
10136
10137                         break;
10138                 default:
10139                         DEBUG(1,("xcvtcp_addport: "
10140                                 "unknown version of port_data: %d\n", version));
10141                         return WERR_UNKNOWN_PORT;
10142         }
10143
10144         /* create the device URI and call the add_port_hook() */
10145
10146         switch (protocol) {
10147         case PROTOCOL_RAWTCP_TYPE:
10148                 device_uri = talloc_asprintf(mem_ctx,
10149                                 "socket://%s:%d/", hostaddress,
10150                                 port_number);
10151                 break;
10152
10153         case PROTOCOL_LPR_TYPE:
10154                 device_uri = talloc_asprintf(mem_ctx,
10155                         "lpr://%s/%s", hostaddress, queue );
10156                 break;
10157
10158         default:
10159                 return WERR_UNKNOWN_PORT;
10160         }
10161
10162         if (!device_uri) {
10163                 return WERR_NOMEM;
10164         }
10165
10166         return add_port_hook(mem_ctx, token, portname, device_uri);
10167 }
10168
10169 /*******************************************************************
10170 *******************************************************************/
10171
10172 struct xcv_api_table xcvtcp_cmds[] = {
10173         { "MonitorUI",  xcvtcp_monitorui },
10174         { "AddPort",    xcvtcp_addport},
10175         { NULL,         NULL }
10176 };
10177
10178 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10179                                      struct security_token *token, const char *command,
10180                                      DATA_BLOB *inbuf,
10181                                      DATA_BLOB *outbuf,
10182                                      uint32_t *needed )
10183 {
10184         int i;
10185
10186         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10187
10188         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10189                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10190                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10191         }
10192
10193         return WERR_BADFUNC;
10194 }
10195
10196 /*******************************************************************
10197 *******************************************************************/
10198 #if 0   /* don't support management using the "Local Port" monitor */
10199
10200 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10201                                  struct security_token *token, DATA_BLOB *in,
10202                                  DATA_BLOB *out, uint32_t *needed)
10203 {
10204         const char *dllname = "localui.dll";
10205
10206         *needed = (strlen(dllname)+1) * 2;
10207
10208         if (out->length < *needed) {
10209                 return WERR_INSUFFICIENT_BUFFER;
10210         }
10211
10212         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10213                 return WERR_NOMEM;
10214         }
10215
10216         return WERR_OK;
10217 }
10218
10219 /*******************************************************************
10220 *******************************************************************/
10221
10222 struct xcv_api_table xcvlocal_cmds[] = {
10223         { "MonitorUI",  xcvlocal_monitorui },
10224         { NULL,         NULL }
10225 };
10226 #else
10227 struct xcv_api_table xcvlocal_cmds[] = {
10228         { NULL,         NULL }
10229 };
10230 #endif
10231
10232
10233
10234 /*******************************************************************
10235 *******************************************************************/
10236
10237 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10238                                        struct security_token *token, const char *command,
10239                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10240                                        uint32_t *needed)
10241 {
10242         int i;
10243
10244         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10245
10246         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10247                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10248                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10249         }
10250         return WERR_BADFUNC;
10251 }
10252
10253 /****************************************************************
10254  _spoolss_XcvData
10255 ****************************************************************/
10256
10257 WERROR _spoolss_XcvData(struct pipes_struct *p,
10258                         struct spoolss_XcvData *r)
10259 {
10260         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10261         DATA_BLOB out_data = data_blob_null;
10262         WERROR werror;
10263
10264         if (!Printer) {
10265                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10266                         OUR_HANDLE(r->in.handle)));
10267                 return WERR_BADFID;
10268         }
10269
10270         /* Has to be a handle to the TCP/IP port monitor */
10271
10272         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10273                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10274                 return WERR_BADFID;
10275         }
10276
10277         /* requires administrative access to the server */
10278
10279         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10280                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10281                 return WERR_ACCESS_DENIED;
10282         }
10283
10284         /* Allocate the outgoing buffer */
10285
10286         if (r->in.out_data_size) {
10287                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10288                 if (out_data.data == NULL) {
10289                         return WERR_NOMEM;
10290                 }
10291         }
10292
10293         switch ( Printer->printer_type ) {
10294         case SPLHND_PORTMON_TCP:
10295                 werror = process_xcvtcp_command(p->mem_ctx,
10296                                                 p->session_info->security_token,
10297                                                 r->in.function_name,
10298                                                 &r->in.in_data, &out_data,
10299                                                 r->out.needed);
10300                 break;
10301         case SPLHND_PORTMON_LOCAL:
10302                 werror = process_xcvlocal_command(p->mem_ctx,
10303                                                   p->session_info->security_token,
10304                                                   r->in.function_name,
10305                                                   &r->in.in_data, &out_data,
10306                                                   r->out.needed);
10307                 break;
10308         default:
10309                 werror = WERR_INVALID_PRINT_MONITOR;
10310         }
10311
10312         if (!W_ERROR_IS_OK(werror)) {
10313                 return werror;
10314         }
10315
10316         *r->out.status_code = 0;
10317
10318         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10319                 memcpy(r->out.out_data, out_data.data,
10320                         MIN(r->in.out_data_size, out_data.length));
10321         }
10322
10323         return WERR_OK;
10324 }
10325
10326 /****************************************************************
10327  _spoolss_AddPrintProcessor
10328 ****************************************************************/
10329
10330 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10331                                   struct spoolss_AddPrintProcessor *r)
10332 {
10333         /* for now, just indicate success and ignore the add.  We'll
10334            automatically set the winprint processor for printer
10335            entries later.  Used to debug the LexMark Optra S 1855 PCL
10336            driver --jerry */
10337
10338         return WERR_OK;
10339 }
10340
10341 /****************************************************************
10342  _spoolss_AddPort
10343 ****************************************************************/
10344
10345 WERROR _spoolss_AddPort(struct pipes_struct *p,
10346                         struct spoolss_AddPort *r)
10347 {
10348         /* do what w2k3 does */
10349
10350         return WERR_NOT_SUPPORTED;
10351 }
10352
10353 /****************************************************************
10354  _spoolss_GetPrinterDriver
10355 ****************************************************************/
10356
10357 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10358                                  struct spoolss_GetPrinterDriver *r)
10359 {
10360         p->rng_fault_state = true;
10361         return WERR_NOT_SUPPORTED;
10362 }
10363
10364 /****************************************************************
10365  _spoolss_ReadPrinter
10366 ****************************************************************/
10367
10368 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10369                             struct spoolss_ReadPrinter *r)
10370 {
10371         p->rng_fault_state = true;
10372         return WERR_NOT_SUPPORTED;
10373 }
10374
10375 /****************************************************************
10376  _spoolss_WaitForPrinterChange
10377 ****************************************************************/
10378
10379 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10380                                      struct spoolss_WaitForPrinterChange *r)
10381 {
10382         p->rng_fault_state = true;
10383         return WERR_NOT_SUPPORTED;
10384 }
10385
10386 /****************************************************************
10387  _spoolss_ConfigurePort
10388 ****************************************************************/
10389
10390 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10391                               struct spoolss_ConfigurePort *r)
10392 {
10393         p->rng_fault_state = true;
10394         return WERR_NOT_SUPPORTED;
10395 }
10396
10397 /****************************************************************
10398  _spoolss_DeletePort
10399 ****************************************************************/
10400
10401 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10402                            struct spoolss_DeletePort *r)
10403 {
10404         p->rng_fault_state = true;
10405         return WERR_NOT_SUPPORTED;
10406 }
10407
10408 /****************************************************************
10409  _spoolss_CreatePrinterIC
10410 ****************************************************************/
10411
10412 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10413                                 struct spoolss_CreatePrinterIC *r)
10414 {
10415         p->rng_fault_state = true;
10416         return WERR_NOT_SUPPORTED;
10417 }
10418
10419 /****************************************************************
10420  _spoolss_PlayGDIScriptOnPrinterIC
10421 ****************************************************************/
10422
10423 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10424                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10425 {
10426         p->rng_fault_state = true;
10427         return WERR_NOT_SUPPORTED;
10428 }
10429
10430 /****************************************************************
10431  _spoolss_DeletePrinterIC
10432 ****************************************************************/
10433
10434 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10435                                 struct spoolss_DeletePrinterIC *r)
10436 {
10437         p->rng_fault_state = true;
10438         return WERR_NOT_SUPPORTED;
10439 }
10440
10441 /****************************************************************
10442  _spoolss_AddPrinterConnection
10443 ****************************************************************/
10444
10445 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10446                                      struct spoolss_AddPrinterConnection *r)
10447 {
10448         p->rng_fault_state = true;
10449         return WERR_NOT_SUPPORTED;
10450 }
10451
10452 /****************************************************************
10453  _spoolss_DeletePrinterConnection
10454 ****************************************************************/
10455
10456 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10457                                         struct spoolss_DeletePrinterConnection *r)
10458 {
10459         p->rng_fault_state = true;
10460         return WERR_NOT_SUPPORTED;
10461 }
10462
10463 /****************************************************************
10464  _spoolss_PrinterMessageBox
10465 ****************************************************************/
10466
10467 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10468                                   struct spoolss_PrinterMessageBox *r)
10469 {
10470         p->rng_fault_state = true;
10471         return WERR_NOT_SUPPORTED;
10472 }
10473
10474 /****************************************************************
10475  _spoolss_AddMonitor
10476 ****************************************************************/
10477
10478 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10479                            struct spoolss_AddMonitor *r)
10480 {
10481         p->rng_fault_state = true;
10482         return WERR_NOT_SUPPORTED;
10483 }
10484
10485 /****************************************************************
10486  _spoolss_DeleteMonitor
10487 ****************************************************************/
10488
10489 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10490                               struct spoolss_DeleteMonitor *r)
10491 {
10492         p->rng_fault_state = true;
10493         return WERR_NOT_SUPPORTED;
10494 }
10495
10496 /****************************************************************
10497  _spoolss_DeletePrintProcessor
10498 ****************************************************************/
10499
10500 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10501                                      struct spoolss_DeletePrintProcessor *r)
10502 {
10503         p->rng_fault_state = true;
10504         return WERR_NOT_SUPPORTED;
10505 }
10506
10507 /****************************************************************
10508  _spoolss_AddPrintProvidor
10509 ****************************************************************/
10510
10511 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10512                                  struct spoolss_AddPrintProvidor *r)
10513 {
10514         p->rng_fault_state = true;
10515         return WERR_NOT_SUPPORTED;
10516 }
10517
10518 /****************************************************************
10519  _spoolss_DeletePrintProvidor
10520 ****************************************************************/
10521
10522 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10523                                     struct spoolss_DeletePrintProvidor *r)
10524 {
10525         p->rng_fault_state = true;
10526         return WERR_NOT_SUPPORTED;
10527 }
10528
10529 /****************************************************************
10530  _spoolss_FindFirstPrinterChangeNotification
10531 ****************************************************************/
10532
10533 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10534                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10535 {
10536         p->rng_fault_state = true;
10537         return WERR_NOT_SUPPORTED;
10538 }
10539
10540 /****************************************************************
10541  _spoolss_FindNextPrinterChangeNotification
10542 ****************************************************************/
10543
10544 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10545                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10546 {
10547         p->rng_fault_state = true;
10548         return WERR_NOT_SUPPORTED;
10549 }
10550
10551 /****************************************************************
10552  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10553 ****************************************************************/
10554
10555 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10556                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10557 {
10558         p->rng_fault_state = true;
10559         return WERR_NOT_SUPPORTED;
10560 }
10561
10562 /****************************************************************
10563  _spoolss_ReplyOpenPrinter
10564 ****************************************************************/
10565
10566 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10567                                  struct spoolss_ReplyOpenPrinter *r)
10568 {
10569         p->rng_fault_state = true;
10570         return WERR_NOT_SUPPORTED;
10571 }
10572
10573 /****************************************************************
10574  _spoolss_RouterReplyPrinter
10575 ****************************************************************/
10576
10577 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10578                                    struct spoolss_RouterReplyPrinter *r)
10579 {
10580         p->rng_fault_state = true;
10581         return WERR_NOT_SUPPORTED;
10582 }
10583
10584 /****************************************************************
10585  _spoolss_ReplyClosePrinter
10586 ****************************************************************/
10587
10588 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10589                                   struct spoolss_ReplyClosePrinter *r)
10590 {
10591         p->rng_fault_state = true;
10592         return WERR_NOT_SUPPORTED;
10593 }
10594
10595 /****************************************************************
10596  _spoolss_AddPortEx
10597 ****************************************************************/
10598
10599 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10600                           struct spoolss_AddPortEx *r)
10601 {
10602         p->rng_fault_state = true;
10603         return WERR_NOT_SUPPORTED;
10604 }
10605
10606 /****************************************************************
10607  _spoolss_RouterFindFirstPrinterChangeNotification
10608 ****************************************************************/
10609
10610 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10611                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10612 {
10613         p->rng_fault_state = true;
10614         return WERR_NOT_SUPPORTED;
10615 }
10616
10617 /****************************************************************
10618  _spoolss_SpoolerInit
10619 ****************************************************************/
10620
10621 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10622                             struct spoolss_SpoolerInit *r)
10623 {
10624         p->rng_fault_state = true;
10625         return WERR_NOT_SUPPORTED;
10626 }
10627
10628 /****************************************************************
10629  _spoolss_ResetPrinterEx
10630 ****************************************************************/
10631
10632 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10633                                struct spoolss_ResetPrinterEx *r)
10634 {
10635         p->rng_fault_state = true;
10636         return WERR_NOT_SUPPORTED;
10637 }
10638
10639 /****************************************************************
10640  _spoolss_RouterReplyPrinterEx
10641 ****************************************************************/
10642
10643 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10644                                      struct spoolss_RouterReplyPrinterEx *r)
10645 {
10646         p->rng_fault_state = true;
10647         return WERR_NOT_SUPPORTED;
10648 }
10649
10650 /****************************************************************
10651  _spoolss_44
10652 ****************************************************************/
10653
10654 WERROR _spoolss_44(struct pipes_struct *p,
10655                    struct spoolss_44 *r)
10656 {
10657         p->rng_fault_state = true;
10658         return WERR_NOT_SUPPORTED;
10659 }
10660
10661 /****************************************************************
10662  _spoolss_SetPort
10663 ****************************************************************/
10664
10665 WERROR _spoolss_SetPort(struct pipes_struct *p,
10666                         struct spoolss_SetPort *r)
10667 {
10668         p->rng_fault_state = true;
10669         return WERR_NOT_SUPPORTED;
10670 }
10671
10672 /****************************************************************
10673  _spoolss_4a
10674 ****************************************************************/
10675
10676 WERROR _spoolss_4a(struct pipes_struct *p,
10677                    struct spoolss_4a *r)
10678 {
10679         p->rng_fault_state = true;
10680         return WERR_NOT_SUPPORTED;
10681 }
10682
10683 /****************************************************************
10684  _spoolss_4b
10685 ****************************************************************/
10686
10687 WERROR _spoolss_4b(struct pipes_struct *p,
10688                    struct spoolss_4b *r)
10689 {
10690         p->rng_fault_state = true;
10691         return WERR_NOT_SUPPORTED;
10692 }
10693
10694 /****************************************************************
10695  _spoolss_4c
10696 ****************************************************************/
10697
10698 WERROR _spoolss_4c(struct pipes_struct *p,
10699                    struct spoolss_4c *r)
10700 {
10701         p->rng_fault_state = true;
10702         return WERR_NOT_SUPPORTED;
10703 }
10704
10705 /****************************************************************
10706  _spoolss_53
10707 ****************************************************************/
10708
10709 WERROR _spoolss_53(struct pipes_struct *p,
10710                    struct spoolss_53 *r)
10711 {
10712         p->rng_fault_state = true;
10713         return WERR_NOT_SUPPORTED;
10714 }
10715
10716 /****************************************************************
10717  _spoolss_AddPerMachineConnection
10718 ****************************************************************/
10719
10720 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10721                                         struct spoolss_AddPerMachineConnection *r)
10722 {
10723         p->rng_fault_state = true;
10724         return WERR_NOT_SUPPORTED;
10725 }
10726
10727 /****************************************************************
10728  _spoolss_DeletePerMachineConnection
10729 ****************************************************************/
10730
10731 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10732                                            struct spoolss_DeletePerMachineConnection *r)
10733 {
10734         p->rng_fault_state = true;
10735         return WERR_NOT_SUPPORTED;
10736 }
10737
10738 /****************************************************************
10739  _spoolss_EnumPerMachineConnections
10740 ****************************************************************/
10741
10742 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10743                                           struct spoolss_EnumPerMachineConnections *r)
10744 {
10745         p->rng_fault_state = true;
10746         return WERR_NOT_SUPPORTED;
10747 }
10748
10749 /****************************************************************
10750  _spoolss_5a
10751 ****************************************************************/
10752
10753 WERROR _spoolss_5a(struct pipes_struct *p,
10754                    struct spoolss_5a *r)
10755 {
10756         p->rng_fault_state = true;
10757         return WERR_NOT_SUPPORTED;
10758 }
10759
10760 /****************************************************************
10761  _spoolss_5b
10762 ****************************************************************/
10763
10764 WERROR _spoolss_5b(struct pipes_struct *p,
10765                    struct spoolss_5b *r)
10766 {
10767         p->rng_fault_state = true;
10768         return WERR_NOT_SUPPORTED;
10769 }
10770
10771 /****************************************************************
10772  _spoolss_5c
10773 ****************************************************************/
10774
10775 WERROR _spoolss_5c(struct pipes_struct *p,
10776                    struct spoolss_5c *r)
10777 {
10778         p->rng_fault_state = true;
10779         return WERR_NOT_SUPPORTED;
10780 }
10781
10782 /****************************************************************
10783  _spoolss_5d
10784 ****************************************************************/
10785
10786 WERROR _spoolss_5d(struct pipes_struct *p,
10787                    struct spoolss_5d *r)
10788 {
10789         p->rng_fault_state = true;
10790         return WERR_NOT_SUPPORTED;
10791 }
10792
10793 /****************************************************************
10794  _spoolss_5e
10795 ****************************************************************/
10796
10797 WERROR _spoolss_5e(struct pipes_struct *p,
10798                    struct spoolss_5e *r)
10799 {
10800         p->rng_fault_state = true;
10801         return WERR_NOT_SUPPORTED;
10802 }
10803
10804 /****************************************************************
10805  _spoolss_5f
10806 ****************************************************************/
10807
10808 WERROR _spoolss_5f(struct pipes_struct *p,
10809                    struct spoolss_5f *r)
10810 {
10811         p->rng_fault_state = true;
10812         return WERR_NOT_SUPPORTED;
10813 }
10814
10815 /****************************************************************
10816  _spoolss_60
10817 ****************************************************************/
10818
10819 WERROR _spoolss_60(struct pipes_struct *p,
10820                    struct spoolss_60 *r)
10821 {
10822         p->rng_fault_state = true;
10823         return WERR_NOT_SUPPORTED;
10824 }
10825
10826 /****************************************************************
10827  _spoolss_61
10828 ****************************************************************/
10829
10830 WERROR _spoolss_61(struct pipes_struct *p,
10831                    struct spoolss_61 *r)
10832 {
10833         p->rng_fault_state = true;
10834         return WERR_NOT_SUPPORTED;
10835 }
10836
10837 /****************************************************************
10838  _spoolss_62
10839 ****************************************************************/
10840
10841 WERROR _spoolss_62(struct pipes_struct *p,
10842                    struct spoolss_62 *r)
10843 {
10844         p->rng_fault_state = true;
10845         return WERR_NOT_SUPPORTED;
10846 }
10847
10848 /****************************************************************
10849  _spoolss_63
10850 ****************************************************************/
10851
10852 WERROR _spoolss_63(struct pipes_struct *p,
10853                    struct spoolss_63 *r)
10854 {
10855         p->rng_fault_state = true;
10856         return WERR_NOT_SUPPORTED;
10857 }
10858
10859 /****************************************************************
10860  _spoolss_64
10861 ****************************************************************/
10862
10863 WERROR _spoolss_64(struct pipes_struct *p,
10864                    struct spoolss_64 *r)
10865 {
10866         p->rng_fault_state = true;
10867         return WERR_NOT_SUPPORTED;
10868 }
10869
10870 /****************************************************************
10871  _spoolss_65
10872 ****************************************************************/
10873
10874 WERROR _spoolss_65(struct pipes_struct *p,
10875                    struct spoolss_65 *r)
10876 {
10877         p->rng_fault_state = true;
10878         return WERR_NOT_SUPPORTED;
10879 }
10880
10881 /****************************************************************
10882  _spoolss_GetCorePrinterDrivers
10883 ****************************************************************/
10884
10885 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10886                                       struct spoolss_GetCorePrinterDrivers *r)
10887 {
10888         p->rng_fault_state = true;
10889         return WERR_NOT_SUPPORTED;
10890 }
10891
10892 /****************************************************************
10893  _spoolss_67
10894 ****************************************************************/
10895
10896 WERROR _spoolss_67(struct pipes_struct *p,
10897                    struct spoolss_67 *r)
10898 {
10899         p->rng_fault_state = true;
10900         return WERR_NOT_SUPPORTED;
10901 }
10902
10903 /****************************************************************
10904  _spoolss_GetPrinterDriverPackagePath
10905 ****************************************************************/
10906
10907 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10908                                             struct spoolss_GetPrinterDriverPackagePath *r)
10909 {
10910         p->rng_fault_state = true;
10911         return WERR_NOT_SUPPORTED;
10912 }
10913
10914 /****************************************************************
10915  _spoolss_69
10916 ****************************************************************/
10917
10918 WERROR _spoolss_69(struct pipes_struct *p,
10919                    struct spoolss_69 *r)
10920 {
10921         p->rng_fault_state = true;
10922         return WERR_NOT_SUPPORTED;
10923 }
10924
10925 /****************************************************************
10926  _spoolss_6a
10927 ****************************************************************/
10928
10929 WERROR _spoolss_6a(struct pipes_struct *p,
10930                    struct spoolss_6a *r)
10931 {
10932         p->rng_fault_state = true;
10933         return WERR_NOT_SUPPORTED;
10934 }
10935
10936 /****************************************************************
10937  _spoolss_6b
10938 ****************************************************************/
10939
10940 WERROR _spoolss_6b(struct pipes_struct *p,
10941                    struct spoolss_6b *r)
10942 {
10943         p->rng_fault_state = true;
10944         return WERR_NOT_SUPPORTED;
10945 }
10946
10947 /****************************************************************
10948  _spoolss_6c
10949 ****************************************************************/
10950
10951 WERROR _spoolss_6c(struct pipes_struct *p,
10952                    struct spoolss_6c *r)
10953 {
10954         p->rng_fault_state = true;
10955         return WERR_NOT_SUPPORTED;
10956 }
10957
10958 /****************************************************************
10959  _spoolss_6d
10960 ****************************************************************/
10961
10962 WERROR _spoolss_6d(struct pipes_struct *p,
10963                    struct spoolss_6d *r)
10964 {
10965         p->rng_fault_state = true;
10966         return WERR_NOT_SUPPORTED;
10967 }