531b2898ab0d2093decf3f915746061693666b03
[kai/samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "include/printing.h"
42 #include "secrets.h"
43 #include "../librpc/gen_ndr/netlogon.h"
44 #include "rpc_misc.h"
45 #include "printing/notify.h"
46 #include "serverid.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "smbd/globals.h"
50 #include "auth.h"
51 #include "messages.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
53 #include "util_tdb.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
58 #include "../libcli/smb/smbXcli_base.h"
59
60 /* macros stolen from s4 spoolss server */
61 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
62         ((info)?ndr_size_##fn(info, level, 0):0)
63
64 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
65         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
66
67 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
68         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
69
70 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
71
72 #undef DBGC_CLASS
73 #define DBGC_CLASS DBGC_RPC_SRV
74
75 #ifndef MAX_OPEN_PRINTER_EXS
76 #define MAX_OPEN_PRINTER_EXS 50
77 #endif
78
79 struct notify_back_channel;
80
81 /* structure to store the printer handles */
82 /* and a reference to what it's pointing to */
83 /* and the notify info asked about */
84 /* that's the central struct */
85 struct printer_handle {
86         struct printer_handle *prev, *next;
87         bool document_started;
88         bool page_started;
89         uint32 jobid; /* jobid in printing backend */
90         int printer_type;
91         const char *servername;
92         fstring sharename;
93         uint32 type;
94         uint32 access_granted;
95         struct {
96                 uint32 flags;
97                 uint32 options;
98                 fstring localmachine;
99                 uint32 printerlocal;
100                 struct spoolss_NotifyOption *option;
101                 struct policy_handle cli_hnd;
102                 struct notify_back_channel *cli_chan;
103                 uint32 change;
104                 /* are we in a FindNextPrinterChangeNotify() call? */
105                 bool fnpcn;
106                 struct messaging_context *msg_ctx;
107         } notify;
108         struct {
109                 fstring machine;
110                 fstring user;
111         } client;
112
113         /* devmode sent in the OpenPrinter() call */
114         struct spoolss_DeviceMode *devmode;
115
116         /* TODO cache the printer info2 structure */
117         struct spoolss_PrinterInfo2 *info2;
118
119 };
120
121 static struct printer_handle *printers_list;
122
123 struct printer_session_counter {
124         struct printer_session_counter *next;
125         struct printer_session_counter *prev;
126
127         int snum;
128         uint32_t counter;
129 };
130
131 static struct printer_session_counter *counter_list;
132
133 struct notify_back_channel {
134         struct notify_back_channel *prev, *next;
135
136         /* associated client */
137         struct sockaddr_storage client_address;
138
139         /* print notify back-channel pipe handle*/
140         struct rpc_pipe_client *cli_pipe;
141         uint32_t active_connections;
142 };
143
144 static struct notify_back_channel *back_channels;
145
146 /* Map generic permissions to printer object specific permissions */
147
148 const struct standard_mapping printer_std_mapping = {
149         PRINTER_READ,
150         PRINTER_WRITE,
151         PRINTER_EXECUTE,
152         PRINTER_ALL_ACCESS
153 };
154
155 /* Map generic permissions to print server object specific permissions */
156
157 const struct standard_mapping printserver_std_mapping = {
158         SERVER_READ,
159         SERVER_WRITE,
160         SERVER_EXECUTE,
161         SERVER_ALL_ACCESS
162 };
163
164 /* API table for Xcv Monitor functions */
165
166 struct xcv_api_table {
167         const char *name;
168         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
169 };
170
171 static void prune_printername_cache(void);
172
173 /********************************************************************
174  * Canonicalize servername.
175  ********************************************************************/
176
177 static const char *canon_servername(const char *servername)
178 {
179         const char *pservername = servername;
180         while (*pservername == '\\') {
181                 pservername++;
182         }
183         return pservername;
184 }
185
186 /* translate between internal status numbers and NT status numbers */
187 static int nt_printj_status(int v)
188 {
189         switch (v) {
190         case LPQ_QUEUED:
191                 return 0;
192         case LPQ_PAUSED:
193                 return JOB_STATUS_PAUSED;
194         case LPQ_SPOOLING:
195                 return JOB_STATUS_SPOOLING;
196         case LPQ_PRINTING:
197                 return JOB_STATUS_PRINTING;
198         case LPQ_ERROR:
199                 return JOB_STATUS_ERROR;
200         case LPQ_DELETING:
201                 return JOB_STATUS_DELETING;
202         case LPQ_OFFLINE:
203                 return JOB_STATUS_OFFLINE;
204         case LPQ_PAPEROUT:
205                 return JOB_STATUS_PAPEROUT;
206         case LPQ_PRINTED:
207                 return JOB_STATUS_PRINTED;
208         case LPQ_DELETED:
209                 return JOB_STATUS_DELETED;
210         case LPQ_BLOCKED:
211                 return JOB_STATUS_BLOCKED_DEVQ;
212         case LPQ_USER_INTERVENTION:
213                 return JOB_STATUS_USER_INTERVENTION;
214         }
215         return 0;
216 }
217
218 static int nt_printq_status(int v)
219 {
220         switch (v) {
221         case LPQ_PAUSED:
222                 return PRINTER_STATUS_PAUSED;
223         case LPQ_QUEUED:
224         case LPQ_SPOOLING:
225         case LPQ_PRINTING:
226                 return 0;
227         }
228         return 0;
229 }
230
231 /***************************************************************************
232  Disconnect from the client
233 ****************************************************************************/
234
235 static void srv_spoolss_replycloseprinter(int snum,
236                                           struct printer_handle *prn_hnd)
237 {
238         WERROR result;
239         NTSTATUS status;
240
241         /*
242          * Tell the specific printing tdb we no longer want messages for this printer
243          * by deregistering our PID.
244          */
245
246         if (!print_notify_deregister_pid(snum)) {
247                 DEBUG(0, ("Failed to register our pid for printer %s\n",
248                           lp_const_servicename(snum)));
249         }
250
251         /* weird if the test succeeds !!! */
252         if (prn_hnd->notify.cli_chan == NULL ||
253             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
254             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
255             prn_hnd->notify.cli_chan->active_connections == 0) {
256                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
257                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
258                 TALLOC_FREE(prn_hnd->notify.cli_chan);
259                 return;
260         }
261
262         status = dcerpc_spoolss_ReplyClosePrinter(
263                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
264                                         talloc_tos(),
265                                         &prn_hnd->notify.cli_hnd,
266                                         &result);
267         if (!NT_STATUS_IS_OK(status)) {
268                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
269                           nt_errstr(status)));
270                 result = ntstatus_to_werror(status);
271         } else if (!W_ERROR_IS_OK(result)) {
272                 DEBUG(0, ("reply_close_printer failed [%s].\n",
273                           win_errstr(result)));
274         }
275
276         /* if it's the last connection, deconnect the IPC$ share */
277         if (prn_hnd->notify.cli_chan->active_connections == 1) {
278
279                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
280                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
281                 TALLOC_FREE(prn_hnd->notify.cli_chan);
282
283                 if (prn_hnd->notify.msg_ctx != NULL) {
284                         messaging_deregister(prn_hnd->notify.msg_ctx,
285                                              MSG_PRINTER_NOTIFY2, NULL);
286                 }
287         }
288
289         if (prn_hnd->notify.cli_chan) {
290                 prn_hnd->notify.cli_chan->active_connections--;
291                 prn_hnd->notify.cli_chan = NULL;
292         }
293 }
294
295 /****************************************************************************
296  Functions to free a printer entry datastruct.
297 ****************************************************************************/
298
299 static int printer_entry_destructor(struct printer_handle *Printer)
300 {
301         if (Printer->notify.cli_chan != NULL &&
302             Printer->notify.cli_chan->active_connections > 0) {
303                 int snum = -1;
304
305                 switch(Printer->printer_type) {
306                 case SPLHND_SERVER:
307                         srv_spoolss_replycloseprinter(snum, Printer);
308                         break;
309
310                 case SPLHND_PRINTER:
311                         snum = print_queue_snum(Printer->sharename);
312                         if (snum != -1) {
313                                 srv_spoolss_replycloseprinter(snum, Printer);
314                         }
315                         break;
316                 default:
317                         break;
318                 }
319         }
320
321         Printer->notify.flags=0;
322         Printer->notify.options=0;
323         Printer->notify.localmachine[0]='\0';
324         Printer->notify.printerlocal=0;
325         TALLOC_FREE(Printer->notify.option);
326         TALLOC_FREE(Printer->devmode);
327
328         /* Remove from the internal list. */
329         DLIST_REMOVE(printers_list, Printer);
330         return 0;
331 }
332
333 /****************************************************************************
334   find printer index by handle
335 ****************************************************************************/
336
337 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
338                                                         struct policy_handle *hnd)
339 {
340         struct printer_handle *find_printer = NULL;
341
342         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
343                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
344                 return NULL;
345         }
346
347         return find_printer;
348 }
349
350 /****************************************************************************
351  Close printer index by handle.
352 ****************************************************************************/
353
354 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
355 {
356         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
357
358         if (!Printer) {
359                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
360                         OUR_HANDLE(hnd)));
361                 return false;
362         }
363
364         close_policy_hnd(p, hnd);
365
366         return true;
367 }
368
369 /****************************************************************************
370  Delete a printer given a handle.
371 ****************************************************************************/
372
373 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
374                                   const char *sharename,
375                                   struct messaging_context *msg_ctx)
376 {
377         char *cmd = lp_deleteprinter_cmd(talloc_tos());
378         char *command = NULL;
379         int ret;
380         bool is_print_op = false;
381
382         /* can't fail if we don't try */
383
384         if ( !*cmd )
385                 return WERR_OK;
386
387         command = talloc_asprintf(ctx,
388                         "%s \"%s\"",
389                         cmd, sharename);
390         if (!command) {
391                 return WERR_NOMEM;
392         }
393         if ( token )
394                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
395
396         DEBUG(10,("Running [%s]\n", command));
397
398         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
399
400         if ( is_print_op )
401                 become_root();
402
403         if ( (ret = smbrun(command, NULL)) == 0 ) {
404                 /* Tell everyone we updated smb.conf. */
405                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
406         }
407
408         if ( is_print_op )
409                 unbecome_root();
410
411         /********** END SePrintOperatorPrivlege BLOCK **********/
412
413         DEBUGADD(10,("returned [%d]\n", ret));
414
415         TALLOC_FREE(command);
416
417         if (ret != 0)
418                 return WERR_BADFID; /* What to return here? */
419
420         return WERR_OK;
421 }
422
423 /****************************************************************************
424  Delete a printer given a handle.
425 ****************************************************************************/
426
427 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
428 {
429         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
430         WERROR result;
431
432         if (!Printer) {
433                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
434                         OUR_HANDLE(hnd)));
435                 return WERR_BADFID;
436         }
437
438         /*
439          * It turns out that Windows allows delete printer on a handle
440          * opened by an admin user, then used on a pipe handle created
441          * by an anonymous user..... but they're working on security.... riiight !
442          * JRA.
443          */
444
445         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
446                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
447                 return WERR_ACCESS_DENIED;
448         }
449
450         /* this does not need a become root since the access check has been
451            done on the handle already */
452
453         result = winreg_delete_printer_key_internal(p->mem_ctx,
454                                            get_session_info_system(),
455                                            p->msg_ctx,
456                                            Printer->sharename,
457                                            "");
458         if (!W_ERROR_IS_OK(result)) {
459                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
460                 return WERR_BADFID;
461         }
462
463         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
464                                      Printer->sharename, p->msg_ctx);
465         if (!W_ERROR_IS_OK(result)) {
466                 return result;
467         }
468         prune_printername_cache();
469         return WERR_OK;
470 }
471
472 /****************************************************************************
473  Return the snum of a printer corresponding to an handle.
474 ****************************************************************************/
475
476 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
477                              int *number, struct share_params **params)
478 {
479         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
480
481         if (!Printer) {
482                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
483                         OUR_HANDLE(hnd)));
484                 return false;
485         }
486
487         switch (Printer->printer_type) {
488                 case SPLHND_PRINTER:
489                         DEBUG(4,("short name:%s\n", Printer->sharename));
490                         *number = print_queue_snum(Printer->sharename);
491                         return (*number != -1);
492                 case SPLHND_SERVER:
493                         return false;
494                 default:
495                         return false;
496         }
497 }
498
499 /****************************************************************************
500  Set printer handle type.
501  Check if it's \\server or \\server\printer
502 ****************************************************************************/
503
504 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
505 {
506         DEBUG(3,("Setting printer type=%s\n", handlename));
507
508         /* it's a print server */
509         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
510                 DEBUGADD(4,("Printer is a print server\n"));
511                 Printer->printer_type = SPLHND_SERVER;
512         }
513         /* it's a printer (set_printer_hnd_name() will handle port monitors */
514         else {
515                 DEBUGADD(4,("Printer is a printer\n"));
516                 Printer->printer_type = SPLHND_PRINTER;
517         }
518
519         return true;
520 }
521
522 static void prune_printername_cache_fn(const char *key, const char *value,
523                                        time_t timeout, void *private_data)
524 {
525         gencache_del(key);
526 }
527
528 static void prune_printername_cache(void)
529 {
530         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
531 }
532
533 /****************************************************************************
534  Set printer handle name..  Accept names like \\server, \\server\printer,
535  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
536  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
537  XcvDataPort() interface.
538 ****************************************************************************/
539
540 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
541                                    const struct auth_session_info *session_info,
542                                    struct messaging_context *msg_ctx,
543                                    struct printer_handle *Printer,
544                                    const char *handlename)
545 {
546         int snum;
547         int n_services=lp_numservices();
548         char *aprinter;
549         const char *printername;
550         const char *servername = NULL;
551         fstring sname;
552         bool found = false;
553         struct spoolss_PrinterInfo2 *info2 = NULL;
554         WERROR result;
555         char *p;
556
557         /*
558          * Hopefully nobody names his printers like this. Maybe \ or ,
559          * are illegal in printer names even?
560          */
561         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
562         char *cache_key;
563         char *tmp;
564
565         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
566                 (unsigned long)strlen(handlename)));
567
568         aprinter = discard_const_p(char, handlename);
569         if ( *handlename == '\\' ) {
570                 servername = canon_servername(handlename);
571                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
572                         *aprinter = '\0';
573                         aprinter++;
574                 }
575                 if (!is_myname_or_ipaddr(servername)) {
576                         return WERR_INVALID_PRINTER_NAME;
577                 }
578                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
579                 if (Printer->servername == NULL) {
580                         return WERR_NOMEM;
581                 }
582         }
583
584         if (Printer->printer_type == SPLHND_SERVER) {
585                 return WERR_OK;
586         }
587
588         if (Printer->printer_type != SPLHND_PRINTER) {
589                 return WERR_INVALID_HANDLE;
590         }
591
592         DEBUGADD(5, ("searching for [%s]\n", aprinter));
593
594         p = strchr(aprinter, ',');
595         if (p != NULL) {
596                 char *p2 = p;
597                 p++;
598                 if (*p == ' ') {
599                         p++;
600                 }
601                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
602                         *p2 = '\0';
603                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
604                         *p2 = '\0';
605                 }
606         }
607
608         if (p) {
609                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
610         }
611
612         /* check for the Port Monitor Interface */
613         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
614                 Printer->printer_type = SPLHND_PORTMON_TCP;
615                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
616                 found = true;
617         }
618         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
619                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
620                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
621                 found = true;
622         }
623
624         /*
625          * With hundreds of printers, the "for" loop iterating all
626          * shares can be quite expensive, as it is done on every
627          * OpenPrinter. The loop maps "aprinter" to "sname", the
628          * result of which we cache in gencache.
629          */
630
631         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
632                                     aprinter);
633         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
634
635                 found = (strcmp(tmp, printer_not_found) != 0);
636                 if (!found) {
637                         DEBUG(4, ("Printer %s not found\n", aprinter));
638                         SAFE_FREE(tmp);
639                         return WERR_INVALID_PRINTER_NAME;
640                 }
641                 fstrcpy(sname, tmp);
642                 SAFE_FREE(tmp);
643         }
644
645         /* Search all sharenames first as this is easier than pulling
646            the printer_info_2 off of disk. Don't use find_service() since
647            that calls out to map_username() */
648
649         /* do another loop to look for printernames */
650         for (snum = 0; !found && snum < n_services; snum++) {
651                 const char *printer = lp_const_servicename(snum);
652
653                 /* no point going on if this is not a printer */
654                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
655                         continue;
656                 }
657
658                 /* ignore [printers] share */
659                 if (strequal(printer, "printers")) {
660                         continue;
661                 }
662
663                 fstrcpy(sname, printer);
664                 if (strequal(aprinter, printer)) {
665                         found = true;
666                         break;
667                 }
668
669                 /* no point looking up the printer object if
670                    we aren't allowing printername != sharename */
671                 if (lp_force_printername(snum)) {
672                         continue;
673                 }
674
675                 result = winreg_get_printer_internal(mem_ctx,
676                                             session_info,
677                                             msg_ctx,
678                                             sname,
679                                             &info2);
680                 if ( !W_ERROR_IS_OK(result) ) {
681                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
682                                  sname, win_errstr(result)));
683                         continue;
684                 }
685
686                 printername = strrchr(info2->printername, '\\');
687                 if (printername == NULL) {
688                         printername = info2->printername;
689                 } else {
690                         printername++;
691                 }
692
693                 if (strequal(printername, aprinter)) {
694                         found = true;
695                         break;
696                 }
697
698                 DEBUGADD(10, ("printername: %s\n", printername));
699
700                 TALLOC_FREE(info2);
701         }
702
703         if ( !found ) {
704                 if (cache_key != NULL) {
705                         gencache_set(cache_key, printer_not_found,
706                                      time(NULL)+300);
707                         TALLOC_FREE(cache_key);
708                 }
709                 DEBUGADD(4,("Printer not found\n"));
710                 return WERR_INVALID_PRINTER_NAME;
711         }
712
713         if (cache_key != NULL) {
714                 gencache_set(cache_key, sname, time(NULL)+300);
715                 TALLOC_FREE(cache_key);
716         }
717
718         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
719
720         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
721
722         return WERR_OK;
723 }
724
725 /****************************************************************************
726  Find first available printer slot. creates a printer handle for you.
727  ****************************************************************************/
728
729 static WERROR open_printer_hnd(struct pipes_struct *p,
730                                struct policy_handle *hnd,
731                                const char *name,
732                                uint32_t access_granted)
733 {
734         struct printer_handle *new_printer;
735         WERROR result;
736
737         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
738
739         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
740         if (new_printer == NULL) {
741                 return WERR_NOMEM;
742         }
743         talloc_set_destructor(new_printer, printer_entry_destructor);
744
745         /* This also steals the printer_handle on the policy_handle */
746         if (!create_policy_hnd(p, hnd, new_printer)) {
747                 TALLOC_FREE(new_printer);
748                 return WERR_INVALID_HANDLE;
749         }
750
751         /* Add to the internal list. */
752         DLIST_ADD(printers_list, new_printer);
753
754         new_printer->notify.option=NULL;
755
756         if (!set_printer_hnd_printertype(new_printer, name)) {
757                 close_printer_handle(p, hnd);
758                 return WERR_INVALID_HANDLE;
759         }
760
761         result = set_printer_hnd_name(p->mem_ctx,
762                                       get_session_info_system(),
763                                       p->msg_ctx,
764                                       new_printer, name);
765         if (!W_ERROR_IS_OK(result)) {
766                 close_printer_handle(p, hnd);
767                 return result;
768         }
769
770         new_printer->access_granted = access_granted;
771
772         DEBUG(5, ("%d printer handles active\n",
773                   (int)num_pipe_handles(p)));
774
775         return WERR_OK;
776 }
777
778 /***************************************************************************
779  check to see if the client motify handle is monitoring the notification
780  given by (notify_type, notify_field).
781  **************************************************************************/
782
783 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
784                                       uint16_t notify_field)
785 {
786         return true;
787 }
788
789 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
790                                 uint16_t notify_field)
791 {
792         struct spoolss_NotifyOption *option = p->notify.option;
793         uint32_t i, j;
794
795         /*
796          * Flags should always be zero when the change notify
797          * is registered by the client's spooler.  A user Win32 app
798          * might use the flags though instead of the NOTIFY_OPTION_INFO
799          * --jerry
800          */
801
802         if (!option) {
803                 return false;
804         }
805
806         if (p->notify.flags)
807                 return is_monitoring_event_flags(
808                         p->notify.flags, notify_type, notify_field);
809
810         for (i = 0; i < option->count; i++) {
811
812                 /* Check match for notify_type */
813
814                 if (option->types[i].type != notify_type)
815                         continue;
816
817                 /* Check match for field */
818
819                 for (j = 0; j < option->types[i].count; j++) {
820                         if (option->types[i].fields[j].field == notify_field) {
821                                 return true;
822                         }
823                 }
824         }
825
826         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
827                    p->servername, p->sharename, notify_type, notify_field));
828
829         return false;
830 }
831
832 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
833         _data->data.integer[0] = _integer; \
834         _data->data.integer[1] = 0;
835
836
837 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
838         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
839         if (!_data->data.string.string) {\
840                 _data->data.string.size = 0; \
841         } \
842         _data->data.string.size = strlen_m_term(_p) * 2;
843
844 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
845         _data->data.devmode.devmode = _devmode;
846
847 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
848         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
849         if (!_data->data.sd.sd) { \
850                 _data->data.sd.sd_size = 0; \
851         } \
852         _data->data.sd.sd_size = \
853                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
854
855 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
856                                    struct tm *t,
857                                    const char **pp,
858                                    uint32_t *plen)
859 {
860         struct spoolss_Time st;
861         uint32_t len = 16;
862         char *p;
863
864         if (!init_systemtime(&st, t)) {
865                 return;
866         }
867
868         p = talloc_array(mem_ctx, char, len);
869         if (!p) {
870                 return;
871         }
872
873         /*
874          * Systemtime must be linearized as a set of UINT16's.
875          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
876          */
877
878         SSVAL(p, 0, st.year);
879         SSVAL(p, 2, st.month);
880         SSVAL(p, 4, st.day_of_week);
881         SSVAL(p, 6, st.day);
882         SSVAL(p, 8, st.hour);
883         SSVAL(p, 10, st.minute);
884         SSVAL(p, 12, st.second);
885         SSVAL(p, 14, st.millisecond);
886
887         *pp = p;
888         *plen = len;
889 }
890
891 /* Convert a notification message to a struct spoolss_Notify */
892
893 static void notify_one_value(struct spoolss_notify_msg *msg,
894                              struct spoolss_Notify *data,
895                              TALLOC_CTX *mem_ctx)
896 {
897         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
898 }
899
900 static void notify_string(struct spoolss_notify_msg *msg,
901                           struct spoolss_Notify *data,
902                           TALLOC_CTX *mem_ctx)
903 {
904         /* The length of the message includes the trailing \0 */
905
906         data->data.string.size = msg->len * 2;
907         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
908         if (!data->data.string.string) {
909                 data->data.string.size = 0;
910                 return;
911         }
912 }
913
914 static void notify_system_time(struct spoolss_notify_msg *msg,
915                                struct spoolss_Notify *data,
916                                TALLOC_CTX *mem_ctx)
917 {
918         data->data.string.string = NULL;
919         data->data.string.size = 0;
920
921         if (msg->len != sizeof(time_t)) {
922                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
923                           msg->len));
924                 return;
925         }
926
927         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
928                                &data->data.string.string,
929                                &data->data.string.size);
930 }
931
932 struct notify2_message_table {
933         const char *name;
934         void (*fn)(struct spoolss_notify_msg *msg,
935                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
936 };
937
938 static struct notify2_message_table printer_notify_table[] = {
939         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
940         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
941         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
942         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
943         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
944         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
945         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
946         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
947         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
948         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
949         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
950         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
951         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
952         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
953         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
954         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
955         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
956         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
957         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
958 };
959
960 static struct notify2_message_table job_notify_table[] = {
961         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
962         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
963         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
964         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
965         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
966         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
967         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
968         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
969         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
970         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
971         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
972         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
973         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
974         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
975         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
976         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
977         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
978         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
979         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
980         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
981         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
982         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
983         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
984         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
985 };
986
987
988 /***********************************************************************
989  Allocate talloc context for container object
990  **********************************************************************/
991
992 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
993 {
994         if ( !ctr )
995                 return;
996
997         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
998
999         return;
1000 }
1001
1002 /***********************************************************************
1003  release all allocated memory and zero out structure
1004  **********************************************************************/
1005
1006 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1007 {
1008         if ( !ctr )
1009                 return;
1010
1011         if ( ctr->ctx )
1012                 talloc_destroy(ctr->ctx);
1013
1014         ZERO_STRUCTP(ctr);
1015
1016         return;
1017 }
1018
1019 /***********************************************************************
1020  **********************************************************************/
1021
1022 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1023 {
1024         if ( !ctr )
1025                 return NULL;
1026
1027         return ctr->ctx;
1028 }
1029
1030 /***********************************************************************
1031  **********************************************************************/
1032
1033 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1034 {
1035         if ( !ctr || !ctr->msg_groups )
1036                 return NULL;
1037
1038         if ( idx >= ctr->num_groups )
1039                 return NULL;
1040
1041         return &ctr->msg_groups[idx];
1042
1043 }
1044
1045 /***********************************************************************
1046  How many groups of change messages do we have ?
1047  **********************************************************************/
1048
1049 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1050 {
1051         if ( !ctr )
1052                 return 0;
1053
1054         return ctr->num_groups;
1055 }
1056
1057 /***********************************************************************
1058  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1059  **********************************************************************/
1060
1061 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1062 {
1063         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1064         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1065         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1066         int                             i, new_slot;
1067
1068         if ( !ctr || !msg )
1069                 return 0;
1070
1071         /* loop over all groups looking for a matching printer name */
1072
1073         for ( i=0; i<ctr->num_groups; i++ ) {
1074                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1075                         break;
1076         }
1077
1078         /* add a new group? */
1079
1080         if ( i == ctr->num_groups ) {
1081                 ctr->num_groups++;
1082
1083                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1084                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1085                         return 0;
1086                 }
1087                 ctr->msg_groups = groups;
1088
1089                 /* clear the new entry and set the printer name */
1090
1091                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1092                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1093         }
1094
1095         /* add the change messages; 'i' is the correct index now regardless */
1096
1097         msg_grp = &ctr->msg_groups[i];
1098
1099         msg_grp->num_msgs++;
1100
1101         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1102                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1103                 return 0;
1104         }
1105         msg_grp->msgs = msg_list;
1106
1107         new_slot = msg_grp->num_msgs-1;
1108         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1109
1110         /* need to allocate own copy of data */
1111
1112         if ( msg->len != 0 )
1113                 msg_grp->msgs[new_slot].notify.data = (char *)
1114                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1115
1116         return ctr->num_groups;
1117 }
1118
1119 static void construct_info_data(struct spoolss_Notify *info_data,
1120                                 enum spoolss_NotifyType type,
1121                                 uint16_t field, int id);
1122
1123 /***********************************************************************
1124  Send a change notication message on all handles which have a call
1125  back registered
1126  **********************************************************************/
1127
1128 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1129                                   struct printer_handle *prn_hnd,
1130                                   SPOOLSS_NOTIFY_MSG *messages,
1131                                   uint32_t num_msgs,
1132                                   struct spoolss_Notify **_notifies,
1133                                   int *_count)
1134 {
1135         struct spoolss_Notify *notifies;
1136         SPOOLSS_NOTIFY_MSG *msg;
1137         int count = 0;
1138         uint32_t id;
1139         int i;
1140
1141         notifies = talloc_zero_array(mem_ctx,
1142                                      struct spoolss_Notify, num_msgs);
1143         if (!notifies) {
1144                 return ENOMEM;
1145         }
1146
1147         for (i = 0; i < num_msgs; i++) {
1148
1149                 msg = &messages[i];
1150
1151                 /* Are we monitoring this event? */
1152
1153                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1154                         continue;
1155                 }
1156
1157                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1158                            "for printer [%s]\n",
1159                            msg->type, msg->field, prn_hnd->sharename));
1160
1161                 /*
1162                  * if the is a printer notification handle and not a job
1163                  * notification type, then set the id to 0.
1164                  * Otherwise just use what was specified in the message.
1165                  *
1166                  * When registering change notification on a print server
1167                  * handle we always need to send back the id (snum) matching
1168                  * the printer for which the change took place.
1169                  * For change notify registered on a printer handle,
1170                  * this does not matter and the id should be 0.
1171                  *
1172                  * --jerry
1173                  */
1174
1175                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1176                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1177                         id = 0;
1178                 } else {
1179                         id = msg->id;
1180                 }
1181
1182                 /* Convert unix jobid to smb jobid */
1183
1184                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1185                         id = sysjob_to_jobid(msg->id);
1186
1187                         if (id == -1) {
1188                                 DEBUG(3, ("no such unix jobid %d\n",
1189                                           msg->id));
1190                                 continue;
1191                         }
1192                 }
1193
1194                 construct_info_data(&notifies[count],
1195                                     msg->type, msg->field, id);
1196
1197                 switch(msg->type) {
1198                 case PRINTER_NOTIFY_TYPE:
1199                         if (printer_notify_table[msg->field].fn) {
1200                                 printer_notify_table[msg->field].fn(msg,
1201                                                 &notifies[count], mem_ctx);
1202                         }
1203                         break;
1204
1205                 case JOB_NOTIFY_TYPE:
1206                         if (job_notify_table[msg->field].fn) {
1207                                 job_notify_table[msg->field].fn(msg,
1208                                                 &notifies[count], mem_ctx);
1209                         }
1210                         break;
1211
1212                 default:
1213                         DEBUG(5, ("Unknown notification type %d\n",
1214                                   msg->type));
1215                         continue;
1216                 }
1217
1218                 count++;
1219         }
1220
1221         *_notifies = notifies;
1222         *_count = count;
1223
1224         return 0;
1225 }
1226
1227 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1228                                 struct printer_handle *prn_hnd,
1229                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1230 {
1231         struct spoolss_Notify *notifies;
1232         int count = 0;
1233         union spoolss_ReplyPrinterInfo info;
1234         struct spoolss_NotifyInfo info0;
1235         uint32_t reply_result;
1236         NTSTATUS status;
1237         WERROR werr;
1238         int ret;
1239
1240         /* Is there notification on this handle? */
1241         if (prn_hnd->notify.cli_chan == NULL ||
1242             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1243             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1244             prn_hnd->notify.cli_chan->active_connections == 0) {
1245                 return 0;
1246         }
1247
1248         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1249                    prn_hnd->servername, prn_hnd->sharename));
1250
1251         /* For this printer? Print servers always receive notifications. */
1252         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1253             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1254                 return 0;
1255         }
1256
1257         DEBUG(10,("Our printer\n"));
1258
1259         /* build the array of change notifications */
1260         ret = build_notify2_messages(mem_ctx, prn_hnd,
1261                                      msg_group->msgs,
1262                                      msg_group->num_msgs,
1263                                      &notifies, &count);
1264         if (ret) {
1265                 return ret;
1266         }
1267
1268         info0.version   = 0x2;
1269         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1270         info0.count     = count;
1271         info0.notifies  = notifies;
1272
1273         info.info0 = &info0;
1274
1275         status = dcerpc_spoolss_RouterReplyPrinterEx(
1276                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1277                                 mem_ctx,
1278                                 &prn_hnd->notify.cli_hnd,
1279                                 prn_hnd->notify.change, /* color */
1280                                 prn_hnd->notify.flags,
1281                                 &reply_result,
1282                                 0, /* reply_type, must be 0 */
1283                                 info, &werr);
1284         if (!NT_STATUS_IS_OK(status)) {
1285                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1286                           "failed: %s\n",
1287                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1288                           nt_errstr(status)));
1289                 werr = ntstatus_to_werror(status);
1290         } else if (!W_ERROR_IS_OK(werr)) {
1291                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1292                           "failed: %s\n",
1293                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1294                           win_errstr(werr)));
1295         }
1296         switch (reply_result) {
1297         case 0:
1298                 break;
1299         case PRINTER_NOTIFY_INFO_DISCARDED:
1300         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1301         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1302                 break;
1303         default:
1304                 break;
1305         }
1306
1307         return 0;
1308 }
1309
1310 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1311 {
1312         struct printer_handle    *p;
1313         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1314         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1315         int ret;
1316
1317         if ( !msg_group ) {
1318                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1319                 return;
1320         }
1321
1322         if (!msg_group->msgs) {
1323                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1324                 return;
1325         }
1326
1327         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1328
1329         /* loop over all printers */
1330
1331         for (p = printers_list; p; p = p->next) {
1332                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1333                 if (ret) {
1334                         goto done;
1335                 }
1336         }
1337
1338 done:
1339         DEBUG(8,("send_notify2_changes: Exit...\n"));
1340         return;
1341 }
1342
1343 /***********************************************************************
1344  **********************************************************************/
1345
1346 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1347 {
1348
1349         uint32_t tv_sec, tv_usec;
1350         size_t offset = 0;
1351
1352         /* Unpack message */
1353
1354         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1355                              msg->printer);
1356
1357         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1358                                 &tv_sec, &tv_usec,
1359                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1360
1361         if (msg->len == 0)
1362                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1363                            &msg->notify.value[0], &msg->notify.value[1]);
1364         else
1365                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1366                            &msg->len, &msg->notify.data);
1367
1368         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1369                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1370
1371         tv->tv_sec = tv_sec;
1372         tv->tv_usec = tv_usec;
1373
1374         if (msg->len == 0)
1375                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1376                           msg->notify.value[1]));
1377         else
1378                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1379
1380         return true;
1381 }
1382
1383 /********************************************************************
1384  Receive a notify2 message list
1385  ********************************************************************/
1386
1387 static void receive_notify2_message_list(struct messaging_context *msg,
1388                                          void *private_data,
1389                                          uint32_t msg_type,
1390                                          struct server_id server_id,
1391                                          DATA_BLOB *data)
1392 {
1393         size_t                  msg_count, i;
1394         char                    *buf = (char *)data->data;
1395         char                    *msg_ptr;
1396         size_t                  msg_len;
1397         SPOOLSS_NOTIFY_MSG      notify;
1398         SPOOLSS_NOTIFY_MSG_CTR  messages;
1399         int                     num_groups;
1400
1401         if (data->length < 4) {
1402                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1403                 return;
1404         }
1405
1406         msg_count = IVAL(buf, 0);
1407         msg_ptr = buf + 4;
1408
1409         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1410
1411         if (msg_count == 0) {
1412                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1413                 return;
1414         }
1415
1416         /* initialize the container */
1417
1418         ZERO_STRUCT( messages );
1419         notify_msg_ctr_init( &messages );
1420
1421         /*
1422          * build message groups for each printer identified
1423          * in a change_notify msg.  Remember that a PCN message
1424          * includes the handle returned for the srv_spoolss_replyopenprinter()
1425          * call.  Therefore messages are grouped according to printer handle.
1426          */
1427
1428         for ( i=0; i<msg_count; i++ ) {
1429                 struct timeval msg_tv;
1430
1431                 if (msg_ptr + 4 - buf > data->length) {
1432                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1433                         return;
1434                 }
1435
1436                 msg_len = IVAL(msg_ptr,0);
1437                 msg_ptr += 4;
1438
1439                 if (msg_ptr + msg_len - buf > data->length) {
1440                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1441                         return;
1442                 }
1443
1444                 /* unpack messages */
1445
1446                 ZERO_STRUCT( notify );
1447                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1448                 msg_ptr += msg_len;
1449
1450                 /* add to correct list in container */
1451
1452                 notify_msg_ctr_addmsg( &messages, &notify );
1453
1454                 /* free memory that might have been allocated by notify2_unpack_msg() */
1455
1456                 if ( notify.len != 0 )
1457                         SAFE_FREE( notify.notify.data );
1458         }
1459
1460         /* process each group of messages */
1461
1462         num_groups = notify_msg_ctr_numgroups( &messages );
1463         for ( i=0; i<num_groups; i++ )
1464                 send_notify2_changes( &messages, i );
1465
1466
1467         /* cleanup */
1468
1469         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1470                 (uint32_t)msg_count ));
1471
1472         notify_msg_ctr_destroy( &messages );
1473
1474         return;
1475 }
1476
1477 /********************************************************************
1478  Send a message to ourself about new driver being installed
1479  so we can upgrade the information for each printer bound to this
1480  driver
1481  ********************************************************************/
1482
1483 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1484                                             struct messaging_context *msg_ctx)
1485 {
1486         int len = strlen(drivername);
1487
1488         if (!len)
1489                 return false;
1490
1491         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1492                 drivername));
1493
1494         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1495                            MSG_PRINTER_DRVUPGRADE,
1496                            (const uint8_t *)drivername, len+1);
1497
1498         return true;
1499 }
1500
1501 void srv_spoolss_cleanup(void)
1502 {
1503         struct printer_session_counter *session_counter;
1504
1505         for (session_counter = counter_list;
1506              session_counter != NULL;
1507              session_counter = counter_list) {
1508                 DLIST_REMOVE(counter_list, session_counter);
1509                 TALLOC_FREE(session_counter);
1510         }
1511 }
1512
1513 /**********************************************************************
1514  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1515  over all printers, upgrading ones as necessary
1516  **********************************************************************/
1517
1518 void do_drv_upgrade_printer(struct messaging_context *msg,
1519                             void *private_data,
1520                             uint32_t msg_type,
1521                             struct server_id server_id,
1522                             DATA_BLOB *data)
1523 {
1524         TALLOC_CTX *tmp_ctx;
1525         const struct auth_session_info *session_info = get_session_info_system();
1526         struct spoolss_PrinterInfo2 *pinfo2;
1527         WERROR result;
1528         const char *drivername;
1529         int snum;
1530         int n_services = lp_numservices();
1531         struct dcerpc_binding_handle *b = NULL;
1532
1533         tmp_ctx = talloc_new(NULL);
1534         if (!tmp_ctx) return;
1535
1536         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1537         if (!drivername) {
1538                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1539                 goto done;
1540         }
1541
1542         DEBUG(10, ("do_drv_upgrade_printer: "
1543                    "Got message for new driver [%s]\n", drivername));
1544
1545         /* Iterate the printer list */
1546
1547         for (snum = 0; snum < n_services; snum++) {
1548                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1549                         continue;
1550                 }
1551
1552                 /* ignore [printers] share */
1553                 if (strequal(lp_const_servicename(snum), "printers")) {
1554                         continue;
1555                 }
1556
1557                 if (b == NULL) {
1558                         result = winreg_printer_binding_handle(tmp_ctx,
1559                                                                session_info,
1560                                                                msg,
1561                                                                &b);
1562                         if (!W_ERROR_IS_OK(result)) {
1563                                 break;
1564                         }
1565                 }
1566
1567                 result = winreg_get_printer(tmp_ctx, b,
1568                                             lp_const_servicename(snum),
1569                                             &pinfo2);
1570
1571                 if (!W_ERROR_IS_OK(result)) {
1572                         continue;
1573                 }
1574
1575                 if (!pinfo2->drivername) {
1576                         continue;
1577                 }
1578
1579                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1580                         continue;
1581                 }
1582
1583                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1584
1585                 /* all we care about currently is the change_id */
1586                 result = winreg_printer_update_changeid(tmp_ctx, b,
1587                                                         pinfo2->printername);
1588
1589                 if (!W_ERROR_IS_OK(result)) {
1590                         DEBUG(3, ("do_drv_upgrade_printer: "
1591                                   "Failed to update changeid [%s]\n",
1592                                   win_errstr(result)));
1593                 }
1594         }
1595
1596         /* all done */
1597 done:
1598         talloc_free(tmp_ctx);
1599 }
1600
1601 /********************************************************************
1602  Update the cache for all printq's with a registered client
1603  connection
1604  ********************************************************************/
1605
1606 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1607 {
1608         struct printer_handle *printer = printers_list;
1609         int snum;
1610
1611         /* loop through all printers and update the cache where
1612            a client is connected */
1613         while (printer) {
1614                 if ((printer->printer_type == SPLHND_PRINTER) &&
1615                     ((printer->notify.cli_chan != NULL) &&
1616                      (printer->notify.cli_chan->active_connections > 0))) {
1617                         snum = print_queue_snum(printer->sharename);
1618                         print_queue_status(msg_ctx, snum, NULL, NULL);
1619                 }
1620
1621                 printer = printer->next;
1622         }
1623
1624         return;
1625 }
1626
1627 /****************************************************************
1628  _spoolss_OpenPrinter
1629 ****************************************************************/
1630
1631 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1632                             struct spoolss_OpenPrinter *r)
1633 {
1634         struct spoolss_OpenPrinterEx e;
1635         WERROR werr;
1636
1637         ZERO_STRUCT(e.in.userlevel);
1638
1639         e.in.printername        = r->in.printername;
1640         e.in.datatype           = r->in.datatype;
1641         e.in.devmode_ctr        = r->in.devmode_ctr;
1642         e.in.access_mask        = r->in.access_mask;
1643         e.in.level              = 0;
1644
1645         e.out.handle            = r->out.handle;
1646
1647         werr = _spoolss_OpenPrinterEx(p, &e);
1648
1649         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1650                 /* OpenPrinterEx returns this for a bad
1651                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1652                  * instead.
1653                  */
1654                 werr = WERR_INVALID_PRINTER_NAME;
1655         }
1656
1657         return werr;
1658 }
1659
1660 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1661                               struct spoolss_DeviceMode *orig,
1662                               struct spoolss_DeviceMode **dest)
1663 {
1664         struct spoolss_DeviceMode *dm;
1665
1666         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1667         if (!dm) {
1668                 return WERR_NOMEM;
1669         }
1670
1671         /* copy all values, then duplicate strings and structs */
1672         *dm = *orig;
1673
1674         dm->devicename = talloc_strdup(dm, orig->devicename);
1675         if (!dm->devicename) {
1676                 return WERR_NOMEM;
1677         }
1678         dm->formname = talloc_strdup(dm, orig->formname);
1679         if (!dm->formname) {
1680                 return WERR_NOMEM;
1681         }
1682         if (orig->driverextra_data.data) {
1683                 dm->driverextra_data.data =
1684                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1685                                         orig->driverextra_data.length);
1686                 if (!dm->driverextra_data.data) {
1687                         return WERR_NOMEM;
1688                 }
1689         }
1690
1691         *dest = dm;
1692         return WERR_OK;
1693 }
1694
1695 /****************************************************************
1696  _spoolss_OpenPrinterEx
1697 ****************************************************************/
1698
1699 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1700                               struct spoolss_OpenPrinterEx *r)
1701 {
1702         int snum;
1703         char *raddr;
1704         char *rhost;
1705         struct printer_handle *Printer=NULL;
1706         WERROR result;
1707         int rc;
1708
1709         if (!r->in.printername) {
1710                 return WERR_INVALID_PARAM;
1711         }
1712
1713         if (!*r->in.printername) {
1714                 return WERR_INVALID_PARAM;
1715         }
1716
1717         if (r->in.level > 3) {
1718                 return WERR_INVALID_PARAM;
1719         }
1720         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1721             (r->in.level == 2 && !r->in.userlevel.level2) ||
1722             (r->in.level == 3 && !r->in.userlevel.level3)) {
1723                 return WERR_INVALID_PARAM;
1724         }
1725
1726         /* some sanity check because you can open a printer or a print server */
1727         /* aka: \\server\printer or \\server */
1728
1729         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1730
1731         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1732         if (!W_ERROR_IS_OK(result)) {
1733                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1734                         "for printer %s\n", r->in.printername));
1735                 ZERO_STRUCTP(r->out.handle);
1736                 return result;
1737         }
1738
1739         Printer = find_printer_index_by_hnd(p, r->out.handle);
1740         if ( !Printer ) {
1741                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1742                         "handle we created for printer %s\n", r->in.printername));
1743                 close_printer_handle(p, r->out.handle);
1744                 ZERO_STRUCTP(r->out.handle);
1745                 return WERR_INVALID_PARAM;
1746         }
1747
1748         /*
1749          * First case: the user is opening the print server:
1750          *
1751          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1752          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1753          *
1754          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1755          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1756          * or if the user is listed in the smb.conf printer admin parameter.
1757          *
1758          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1759          * client view printer folder, but does not show the MSAPW.
1760          *
1761          * Note: this test needs code to check access rights here too. Jeremy
1762          * could you look at this?
1763          *
1764          * Second case: the user is opening a printer:
1765          * NT doesn't let us connect to a printer if the connecting user
1766          * doesn't have print permission.
1767          *
1768          * Third case: user is opening a Port Monitor
1769          * access checks same as opening a handle to the print server.
1770          */
1771
1772         switch (Printer->printer_type )
1773         {
1774         case SPLHND_SERVER:
1775         case SPLHND_PORTMON_TCP:
1776         case SPLHND_PORTMON_LOCAL:
1777                 /* Printserver handles use global struct... */
1778
1779                 snum = -1;
1780
1781                 /* Map standard access rights to object specific access rights */
1782
1783                 se_map_standard(&r->in.access_mask,
1784                                 &printserver_std_mapping);
1785
1786                 /* Deny any object specific bits that don't apply to print
1787                    servers (i.e printer and job specific bits) */
1788
1789                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1790
1791                 if (r->in.access_mask &
1792                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1793                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1794                         close_printer_handle(p, r->out.handle);
1795                         ZERO_STRUCTP(r->out.handle);
1796                         return WERR_ACCESS_DENIED;
1797                 }
1798
1799                 /* Allow admin access */
1800
1801                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1802                 {
1803                         if (!lp_ms_add_printer_wizard()) {
1804                                 close_printer_handle(p, r->out.handle);
1805                                 ZERO_STRUCTP(r->out.handle);
1806                                 return WERR_ACCESS_DENIED;
1807                         }
1808
1809                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1810                            and not a printer admin, then fail */
1811
1812                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1813                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1814                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1815                                                 p->session_info->security_token)) {
1816                                 close_printer_handle(p, r->out.handle);
1817                                 ZERO_STRUCTP(r->out.handle);
1818                                 DEBUG(3,("access DENIED as user is not root, "
1819                                         "has no printoperator privilege, "
1820                                         "not a member of the printoperator builtin group and "
1821                                         "is not in printer admin list"));
1822                                 return WERR_ACCESS_DENIED;
1823                         }
1824
1825                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1826                 }
1827                 else
1828                 {
1829                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1830                 }
1831
1832                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1833                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1834
1835                 /* We fall through to return WERR_OK */
1836                 break;
1837
1838         case SPLHND_PRINTER:
1839                 /* NT doesn't let us connect to a printer if the connecting user
1840                    doesn't have print permission.  */
1841
1842                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1843                         close_printer_handle(p, r->out.handle);
1844                         ZERO_STRUCTP(r->out.handle);
1845                         return WERR_BADFID;
1846                 }
1847
1848                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1849                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1850                 }
1851
1852                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1853
1854                 /* map an empty access mask to the minimum access mask */
1855                 if (r->in.access_mask == 0x0)
1856                         r->in.access_mask = PRINTER_ACCESS_USE;
1857
1858                 /*
1859                  * If we are not serving the printer driver for this printer,
1860                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1861                  * will keep NT clients happy  --jerry
1862                  */
1863
1864                 if (lp_use_client_driver(snum)
1865                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1866                 {
1867                         r->in.access_mask = PRINTER_ACCESS_USE;
1868                 }
1869
1870                 /* check smb.conf parameters and the the sec_desc */
1871                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1872                                                          p->mem_ctx);
1873                 if (raddr == NULL) {
1874                         return WERR_NOMEM;
1875                 }
1876
1877                 rc = get_remote_hostname(p->remote_address,
1878                                          &rhost,
1879                                          p->mem_ctx);
1880                 if (rc < 0) {
1881                         return WERR_NOMEM;
1882                 }
1883                 if (strequal(rhost, "UNKNOWN")) {
1884                         rhost = raddr;
1885                 }
1886
1887                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1888                                   rhost, raddr)) {
1889                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1890                         ZERO_STRUCTP(r->out.handle);
1891                         return WERR_ACCESS_DENIED;
1892                 }
1893
1894                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1895                                    p->session_info->security_token, snum) ||
1896                     !print_access_check(p->session_info,
1897                                         p->msg_ctx,
1898                                         snum,
1899                                         r->in.access_mask)) {
1900                         DEBUG(3, ("access DENIED for printer open\n"));
1901                         close_printer_handle(p, r->out.handle);
1902                         ZERO_STRUCTP(r->out.handle);
1903                         return WERR_ACCESS_DENIED;
1904                 }
1905
1906                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1907                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1908                         close_printer_handle(p, r->out.handle);
1909                         ZERO_STRUCTP(r->out.handle);
1910                         return WERR_ACCESS_DENIED;
1911                 }
1912
1913                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1914                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1915                 else
1916                         r->in.access_mask = PRINTER_ACCESS_USE;
1917
1918                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1919                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1920
1921                 winreg_create_printer_internal(p->mem_ctx,
1922                                       get_session_info_system(),
1923                                       p->msg_ctx,
1924                                       lp_const_servicename(snum));
1925
1926                 break;
1927
1928         default:
1929                 /* sanity check to prevent programmer error */
1930                 ZERO_STRUCTP(r->out.handle);
1931                 return WERR_BADFID;
1932         }
1933
1934         Printer->access_granted = r->in.access_mask;
1935
1936         /*
1937          * If the client sent a devmode in the OpenPrinter() call, then
1938          * save it here in case we get a job submission on this handle
1939          */
1940
1941          if ((Printer->printer_type != SPLHND_SERVER)
1942           && (r->in.devmode_ctr.devmode != NULL)) {
1943                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1944                                 &Printer->devmode);
1945          }
1946
1947         return WERR_OK;
1948 }
1949
1950 /****************************************************************
1951  _spoolss_ClosePrinter
1952 ****************************************************************/
1953
1954 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1955                              struct spoolss_ClosePrinter *r)
1956 {
1957         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1958
1959         if (Printer && Printer->document_started) {
1960                 struct spoolss_EndDocPrinter e;
1961
1962                 e.in.handle = r->in.handle;
1963
1964                 _spoolss_EndDocPrinter(p, &e);
1965         }
1966
1967         if (!close_printer_handle(p, r->in.handle))
1968                 return WERR_BADFID;
1969
1970         /* clear the returned printer handle.  Observed behavior
1971            from Win2k server.  Don't think this really matters.
1972            Previous code just copied the value of the closed
1973            handle.    --jerry */
1974
1975         ZERO_STRUCTP(r->out.handle);
1976
1977         return WERR_OK;
1978 }
1979
1980 /****************************************************************
1981  _spoolss_DeletePrinter
1982 ****************************************************************/
1983
1984 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1985                               struct spoolss_DeletePrinter *r)
1986 {
1987         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1988         WERROR result;
1989         int snum;
1990
1991         if (Printer && Printer->document_started) {
1992                 struct spoolss_EndDocPrinter e;
1993
1994                 e.in.handle = r->in.handle;
1995
1996                 _spoolss_EndDocPrinter(p, &e);
1997         }
1998
1999         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2000                 winreg_delete_printer_key_internal(p->mem_ctx,
2001                                           get_session_info_system(),
2002                                           p->msg_ctx,
2003                                           lp_const_servicename(snum),
2004                                           "");
2005         }
2006
2007         result = delete_printer_handle(p, r->in.handle);
2008
2009         return result;
2010 }
2011
2012 /*******************************************************************
2013  * static function to lookup the version id corresponding to an
2014  * long architecture string
2015  ******************************************************************/
2016
2017 static const struct print_architecture_table_node archi_table[]= {
2018
2019         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2020         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2021         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2022         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2023         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2024         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2025         {"Windows x64",          SPL_ARCH_X64,          3 },
2026         {NULL,                   "",            -1 }
2027 };
2028
2029 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2030                                    SPOOLSS_DRIVER_VERSION_NT35,
2031                                    SPOOLSS_DRIVER_VERSION_NT4,
2032                                    SPOOLSS_DRIVER_VERSION_200X,
2033                                    -1};
2034
2035 static int get_version_id(const char *arch)
2036 {
2037         int i;
2038
2039         for (i=0; archi_table[i].long_archi != NULL; i++)
2040         {
2041                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2042                         return (archi_table[i].version);
2043         }
2044
2045         return -1;
2046 }
2047
2048 /****************************************************************
2049  _spoolss_DeletePrinterDriver
2050 ****************************************************************/
2051
2052 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2053                                     struct spoolss_DeletePrinterDriver *r)
2054 {
2055
2056         struct spoolss_DriverInfo8 *info = NULL;
2057         int                             version;
2058         WERROR                          status;
2059         struct dcerpc_binding_handle *b;
2060         TALLOC_CTX *tmp_ctx = NULL;
2061         int i;
2062         bool found;
2063
2064         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2065            and not a printer admin, then fail */
2066
2067         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2068             !security_token_has_privilege(p->session_info->security_token,
2069                                           SEC_PRIV_PRINT_OPERATOR)) {
2070                 return WERR_ACCESS_DENIED;
2071         }
2072
2073         /* check that we have a valid driver name first */
2074
2075         if ((version = get_version_id(r->in.architecture)) == -1) {
2076                 return WERR_INVALID_ENVIRONMENT;
2077         }
2078
2079         tmp_ctx = talloc_new(p->mem_ctx);
2080         if (!tmp_ctx) {
2081                 return WERR_NOMEM;
2082         }
2083
2084         status = winreg_printer_binding_handle(tmp_ctx,
2085                                                get_session_info_system(),
2086                                                p->msg_ctx,
2087                                                &b);
2088         if (!W_ERROR_IS_OK(status)) {
2089                 goto done;
2090         }
2091
2092         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2093                 status = winreg_get_driver(tmp_ctx, b,
2094                                            r->in.architecture, r->in.driver,
2095                                            drv_cversion[i], &info);
2096                 if (!W_ERROR_IS_OK(status)) {
2097                         DEBUG(5, ("skipping del of driver with version %d\n",
2098                                   drv_cversion[i]));
2099                         continue;
2100                 }
2101                 found = true;
2102
2103                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2104                         status = WERR_PRINTER_DRIVER_IN_USE;
2105                         goto done;
2106                 }
2107
2108                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2109                 if (!W_ERROR_IS_OK(status)) {
2110                         DEBUG(0, ("failed del of driver with version %d\n",
2111                                   drv_cversion[i]));
2112                         goto done;
2113                 }
2114         }
2115         if (found == false) {
2116                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2117                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2118         } else {
2119                 status = WERR_OK;
2120         }
2121
2122 done:
2123         talloc_free(tmp_ctx);
2124
2125         return status;
2126 }
2127
2128 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2129                                   struct pipes_struct *p,
2130                                   struct spoolss_DeletePrinterDriverEx *r,
2131                                   struct dcerpc_binding_handle *b,
2132                                   struct spoolss_DriverInfo8 *info)
2133 {
2134         WERROR status;
2135         bool delete_files;
2136
2137         if (printer_driver_in_use(mem_ctx, b, info)) {
2138                 status = WERR_PRINTER_DRIVER_IN_USE;
2139                 goto done;
2140         }
2141
2142         /*
2143          * we have a couple of cases to consider.
2144          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2145          *     then the delete should fail if **any** files overlap with
2146          *     other drivers
2147          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2148          *     non-overlapping files
2149          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2150          *     are set, then do not delete any files
2151          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2152          */
2153
2154         delete_files = r->in.delete_flags
2155                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2156
2157
2158         if (delete_files) {
2159                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2160                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2161                         status = WERR_PRINTER_DRIVER_IN_USE;
2162                         goto done;
2163                 }
2164                 /*
2165                  * printer_driver_files_in_use() has trimmed overlapping files
2166                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2167                  */
2168         }
2169
2170
2171         status = winreg_del_driver(mem_ctx, b, info, info->version);
2172         if (!W_ERROR_IS_OK(status)) {
2173                 goto done;
2174         }
2175
2176         /*
2177          * now delete any associated files if delete_files is
2178          * true. Even if this part failes, we return succes
2179          * because the driver doesn not exist any more
2180          */
2181         if (delete_files) {
2182                 delete_driver_files(p->session_info, info);
2183         }
2184
2185 done:
2186         return status;
2187 }
2188
2189 /****************************************************************
2190  _spoolss_DeletePrinterDriverEx
2191 ****************************************************************/
2192
2193 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2194                                       struct spoolss_DeletePrinterDriverEx *r)
2195 {
2196         struct spoolss_DriverInfo8 *info = NULL;
2197         WERROR                          status;
2198         struct dcerpc_binding_handle *b;
2199         TALLOC_CTX *tmp_ctx = NULL;
2200         int i;
2201         bool found;
2202
2203         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2204            and not a printer admin, then fail */
2205
2206         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2207             !security_token_has_privilege(p->session_info->security_token,
2208                                           SEC_PRIV_PRINT_OPERATOR)) {
2209                 return WERR_ACCESS_DENIED;
2210         }
2211
2212         /* check that we have a valid driver name first */
2213         if (get_version_id(r->in.architecture) == -1) {
2214                 /* this is what NT returns */
2215                 return WERR_INVALID_ENVIRONMENT;
2216         }
2217
2218         tmp_ctx = talloc_new(p->mem_ctx);
2219         if (!tmp_ctx) {
2220                 return WERR_NOMEM;
2221         }
2222
2223         status = winreg_printer_binding_handle(tmp_ctx,
2224                                                get_session_info_system(),
2225                                                p->msg_ctx,
2226                                                &b);
2227         if (!W_ERROR_IS_OK(status)) {
2228                 goto done;
2229         }
2230
2231         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2232                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2233                  && (drv_cversion[i] != r->in.version)) {
2234                         continue;
2235                 }
2236
2237                 /* check if a driver with this version exists before delete */
2238                 status = winreg_get_driver(tmp_ctx, b,
2239                                            r->in.architecture, r->in.driver,
2240                                            drv_cversion[i], &info);
2241                 if (!W_ERROR_IS_OK(status)) {
2242                         DEBUG(5, ("skipping del of driver with version %d\n",
2243                                   drv_cversion[i]));
2244                         continue;
2245                 }
2246                 found = true;
2247
2248                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2249                 if (!W_ERROR_IS_OK(status)) {
2250                         DEBUG(0, ("failed to delete driver with version %d\n",
2251                                   drv_cversion[i]));
2252                         goto done;
2253                 }
2254         }
2255         if (found == false) {
2256                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2257                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2258         } else {
2259                 status = WERR_OK;
2260         }
2261
2262 done:
2263         talloc_free(tmp_ctx);
2264         return status;
2265 }
2266
2267
2268 /********************************************************************
2269  GetPrinterData on a printer server Handle.
2270 ********************************************************************/
2271
2272 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2273                                             const char *value,
2274                                             enum winreg_Type *type,
2275                                             union spoolss_PrinterData *data)
2276 {
2277         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2278
2279         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2280                 *type = REG_DWORD;
2281                 SIVAL(&data->value, 0, 0x00);
2282                 return WERR_OK;
2283         }
2284
2285         if (!strcasecmp_m(value, "BeepEnabled")) {
2286                 *type = REG_DWORD;
2287                 SIVAL(&data->value, 0, 0x00);
2288                 return WERR_OK;
2289         }
2290
2291         if (!strcasecmp_m(value, "EventLog")) {
2292                 *type = REG_DWORD;
2293                 /* formally was 0x1b */
2294                 SIVAL(&data->value, 0, 0x00);
2295                 return WERR_OK;
2296         }
2297
2298         if (!strcasecmp_m(value, "NetPopup")) {
2299                 *type = REG_DWORD;
2300                 SIVAL(&data->value, 0, 0x00);
2301                 return WERR_OK;
2302         }
2303
2304         if (!strcasecmp_m(value, "MajorVersion")) {
2305                 *type = REG_DWORD;
2306
2307                 /* Windows NT 4.0 seems to not allow uploading of drivers
2308                    to a server that reports 0x3 as the MajorVersion.
2309                    need to investigate more how Win2k gets around this .
2310                    -- jerry */
2311
2312                 if (RA_WINNT == get_remote_arch()) {
2313                         SIVAL(&data->value, 0, 0x02);
2314                 } else {
2315                         SIVAL(&data->value, 0, 0x03);
2316                 }
2317
2318                 return WERR_OK;
2319         }
2320
2321         if (!strcasecmp_m(value, "MinorVersion")) {
2322                 *type = REG_DWORD;
2323                 SIVAL(&data->value, 0, 0x00);
2324                 return WERR_OK;
2325         }
2326
2327         /* REG_BINARY
2328          *  uint32_t size        = 0x114
2329          *  uint32_t major       = 5
2330          *  uint32_t minor       = [0|1]
2331          *  uint32_t build       = [2195|2600]
2332          *  extra unicode string = e.g. "Service Pack 3"
2333          */
2334         if (!strcasecmp_m(value, "OSVersion")) {
2335                 DATA_BLOB blob;
2336                 enum ndr_err_code ndr_err;
2337                 struct spoolss_OSVersion os;
2338
2339                 os.major                = 5;    /* Windows 2000 == 5.0 */
2340                 os.minor                = 0;
2341                 os.build                = 2195; /* build */
2342                 os.extra_string         = "";   /* leave extra string empty */
2343
2344                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2345                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2346                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2347                         return WERR_GENERAL_FAILURE;
2348                 }
2349
2350                 *type = REG_BINARY;
2351                 data->binary = blob;
2352
2353                 return WERR_OK;
2354         }
2355
2356
2357         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2358                 *type = REG_SZ;
2359
2360                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2361                 W_ERROR_HAVE_NO_MEMORY(data->string);
2362
2363                 return WERR_OK;
2364         }
2365
2366         if (!strcasecmp_m(value, "Architecture")) {
2367                 *type = REG_SZ;
2368                 data->string = talloc_strdup(mem_ctx,
2369                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2370                 W_ERROR_HAVE_NO_MEMORY(data->string);
2371
2372                 return WERR_OK;
2373         }
2374
2375         if (!strcasecmp_m(value, "DsPresent")) {
2376                 *type = REG_DWORD;
2377
2378                 /* only show the publish check box if we are a
2379                    member of a AD domain */
2380
2381                 if (lp_security() == SEC_ADS) {
2382                         SIVAL(&data->value, 0, 0x01);
2383                 } else {
2384                         SIVAL(&data->value, 0, 0x00);
2385                 }
2386                 return WERR_OK;
2387         }
2388
2389         if (!strcasecmp_m(value, "DNSMachineName")) {
2390                 const char *hostname = get_mydnsfullname();
2391
2392                 if (!hostname) {
2393                         return WERR_BADFILE;
2394                 }
2395
2396                 *type = REG_SZ;
2397                 data->string = talloc_strdup(mem_ctx, hostname);
2398                 W_ERROR_HAVE_NO_MEMORY(data->string);
2399
2400                 return WERR_OK;
2401         }
2402
2403         *type = REG_NONE;
2404
2405         return WERR_INVALID_PARAM;
2406 }
2407
2408 /****************************************************************
2409  _spoolss_GetPrinterData
2410 ****************************************************************/
2411
2412 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2413                                struct spoolss_GetPrinterData *r)
2414 {
2415         struct spoolss_GetPrinterDataEx r2;
2416
2417         r2.in.handle            = r->in.handle;
2418         r2.in.key_name          = "PrinterDriverData";
2419         r2.in.value_name        = r->in.value_name;
2420         r2.in.offered           = r->in.offered;
2421         r2.out.type             = r->out.type;
2422         r2.out.data             = r->out.data;
2423         r2.out.needed           = r->out.needed;
2424
2425         return _spoolss_GetPrinterDataEx(p, &r2);
2426 }
2427
2428 /*********************************************************
2429  Connect to the client machine.
2430 **********************************************************/
2431
2432 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2433                         struct sockaddr_storage *client_ss, const char *remote_machine)
2434 {
2435         NTSTATUS ret;
2436         struct cli_state *the_cli;
2437         struct sockaddr_storage rm_addr;
2438         char addr[INET6_ADDRSTRLEN];
2439
2440         if ( is_zero_addr(client_ss) ) {
2441                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2442                         remote_machine));
2443                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2444                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2445                         return false;
2446                 }
2447                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2448         } else {
2449                 rm_addr = *client_ss;
2450                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2451                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2452                         addr));
2453         }
2454
2455         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2456                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2457                         addr));
2458                 return false;
2459         }
2460
2461         /* setup the connection */
2462         ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2463                 &rm_addr, 0, "IPC$", "IPC",
2464                 "", /* username */
2465                 "", /* domain */
2466                 "", /* password */
2467                 0, lp_client_signing());
2468
2469         if ( !NT_STATUS_IS_OK( ret ) ) {
2470                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2471                         remote_machine ));
2472                 return false;
2473         }
2474
2475         if ( smbXcli_conn_protocol(the_cli->conn) != PROTOCOL_NT1 ) {
2476                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2477                 cli_shutdown(the_cli);
2478                 return false;
2479         }
2480
2481         /*
2482          * Ok - we have an anonymous connection to the IPC$ share.
2483          * Now start the NT Domain stuff :-).
2484          */
2485
2486         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2487         if (!NT_STATUS_IS_OK(ret)) {
2488                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2489                         remote_machine, nt_errstr(ret)));
2490                 cli_shutdown(the_cli);
2491                 return false;
2492         }
2493
2494         return true;
2495 }
2496
2497 /***************************************************************************
2498  Connect to the client.
2499 ****************************************************************************/
2500
2501 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2502                                         uint32_t localprinter,
2503                                         enum winreg_Type type,
2504                                         struct policy_handle *handle,
2505                                         struct notify_back_channel **_chan,
2506                                         struct sockaddr_storage *client_ss,
2507                                         struct messaging_context *msg_ctx)
2508 {
2509         WERROR result;
2510         NTSTATUS status;
2511         struct notify_back_channel *chan;
2512
2513         for (chan = back_channels; chan; chan = chan->next) {
2514                 if (memcmp(&chan->client_address, client_ss,
2515                            sizeof(struct sockaddr_storage)) == 0) {
2516                         break;
2517                 }
2518         }
2519
2520         /*
2521          * If it's the first connection, contact the client
2522          * and connect to the IPC$ share anonymously
2523          */
2524         if (!chan) {
2525                 fstring unix_printer;
2526
2527                 /* the +2 is to strip the leading 2 backslashs */
2528                 fstrcpy(unix_printer, printer + 2);
2529
2530                 chan = talloc_zero(NULL, struct notify_back_channel);
2531                 if (!chan) {
2532                         return false;
2533                 }
2534                 chan->client_address = *client_ss;
2535
2536                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2537                         TALLOC_FREE(chan);
2538                         return false;
2539                 }
2540
2541                 DLIST_ADD(back_channels, chan);
2542
2543                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2544                                    receive_notify2_message_list);
2545         }
2546
2547         if (chan->cli_pipe == NULL ||
2548             chan->cli_pipe->binding_handle == NULL) {
2549                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2550                         "NULL %s for printer %s\n",
2551                         chan->cli_pipe == NULL ?
2552                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2553                         printer));
2554                 return false;
2555         }
2556
2557         /*
2558          * Tell the specific printing tdb we want messages for this printer
2559          * by registering our PID.
2560          */
2561
2562         if (!print_notify_register_pid(snum)) {
2563                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2564                           printer));
2565         }
2566
2567         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2568                                                  talloc_tos(),
2569                                                  printer,
2570                                                  localprinter,
2571                                                  type,
2572                                                  0,
2573                                                  NULL,
2574                                                  handle,
2575                                                  &result);
2576         if (!NT_STATUS_IS_OK(status)) {
2577                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2578                 result = ntstatus_to_werror(status);
2579         } else if (!W_ERROR_IS_OK(result)) {
2580                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2581         }
2582
2583         chan->active_connections++;
2584         *_chan = chan;
2585
2586         return (W_ERROR_IS_OK(result));
2587 }
2588
2589 /****************************************************************
2590  ****************************************************************/
2591
2592 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2593                                                              const struct spoolss_NotifyOption *r)
2594 {
2595         struct spoolss_NotifyOption *option;
2596         uint32_t i,k;
2597
2598         if (!r) {
2599                 return NULL;
2600         }
2601
2602         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2603         if (!option) {
2604                 return NULL;
2605         }
2606
2607         *option = *r;
2608
2609         if (!option->count) {
2610                 return option;
2611         }
2612
2613         option->types = talloc_zero_array(option,
2614                 struct spoolss_NotifyOptionType, option->count);
2615         if (!option->types) {
2616                 talloc_free(option);
2617                 return NULL;
2618         }
2619
2620         for (i=0; i < option->count; i++) {
2621                 option->types[i] = r->types[i];
2622
2623                 if (option->types[i].count) {
2624                         option->types[i].fields = talloc_zero_array(option,
2625                                 union spoolss_Field, option->types[i].count);
2626                         if (!option->types[i].fields) {
2627                                 talloc_free(option);
2628                                 return NULL;
2629                         }
2630                         for (k=0; k<option->types[i].count; k++) {
2631                                 option->types[i].fields[k] =
2632                                         r->types[i].fields[k];
2633                         }
2634                 }
2635         }
2636
2637         return option;
2638 }
2639
2640 /****************************************************************
2641  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2642  *
2643  * before replying OK: status=0 a rpc call is made to the workstation
2644  * asking ReplyOpenPrinter
2645  *
2646  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2647  * called from api_spoolss_rffpcnex
2648 ****************************************************************/
2649
2650 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2651                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2652 {
2653         int snum = -1;
2654         struct spoolss_NotifyOption *option = r->in.notify_options;
2655         struct sockaddr_storage client_ss;
2656         ssize_t client_len;
2657
2658         /* store the notify value in the printer struct */
2659
2660         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2661
2662         if (!Printer) {
2663                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2664                         "Invalid handle (%s:%u:%u).\n",
2665                         OUR_HANDLE(r->in.handle)));
2666                 return WERR_BADFID;
2667         }
2668
2669         Printer->notify.flags           = r->in.flags;
2670         Printer->notify.options         = r->in.options;
2671         Printer->notify.printerlocal    = r->in.printer_local;
2672         Printer->notify.msg_ctx         = p->msg_ctx;
2673
2674         TALLOC_FREE(Printer->notify.option);
2675         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2676
2677         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2678
2679         /* Connect to the client machine and send a ReplyOpenPrinter */
2680
2681         if ( Printer->printer_type == SPLHND_SERVER)
2682                 snum = -1;
2683         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2684                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2685                 return WERR_BADFID;
2686
2687         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2688                   "remote_address is %s\n",
2689                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2690
2691         if (!lp_print_notify_backchannel(snum)) {
2692                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2693                         "backchannel disabled\n"));
2694                 return WERR_SERVER_UNAVAILABLE;
2695         }
2696
2697         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2698                                                   (struct sockaddr *) &client_ss,
2699                                                   sizeof(struct sockaddr_storage));
2700         if (client_len < 0) {
2701                 return WERR_NOMEM;
2702         }
2703
2704         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2705                                         Printer->notify.printerlocal, REG_SZ,
2706                                         &Printer->notify.cli_hnd,
2707                                         &Printer->notify.cli_chan,
2708                                         &client_ss, p->msg_ctx)) {
2709                 return WERR_SERVER_UNAVAILABLE;
2710         }
2711
2712         return WERR_OK;
2713 }
2714
2715 /*******************************************************************
2716  * fill a notify_info_data with the servername
2717  ********************************************************************/
2718
2719 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2720                                        int snum,
2721                                        struct spoolss_Notify *data,
2722                                        print_queue_struct *queue,
2723                                        struct spoolss_PrinterInfo2 *pinfo2,
2724                                        TALLOC_CTX *mem_ctx)
2725 {
2726         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2727 }
2728
2729 /*******************************************************************
2730  * fill a notify_info_data with the printername (not including the servername).
2731  ********************************************************************/
2732
2733 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2734                                         int snum,
2735                                         struct spoolss_Notify *data,
2736                                         print_queue_struct *queue,
2737                                         struct spoolss_PrinterInfo2 *pinfo2,
2738                                         TALLOC_CTX *mem_ctx)
2739 {
2740         /* the notify name should not contain the \\server\ part */
2741         const char *p = strrchr(pinfo2->printername, '\\');
2742
2743         if (!p) {
2744                 p = pinfo2->printername;
2745         } else {
2746                 p++;
2747         }
2748
2749         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2750 }
2751
2752 /*******************************************************************
2753  * fill a notify_info_data with the servicename
2754  ********************************************************************/
2755
2756 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2757                                       int snum,
2758                                       struct spoolss_Notify *data,
2759                                       print_queue_struct *queue,
2760                                       struct spoolss_PrinterInfo2 *pinfo2,
2761                                       TALLOC_CTX *mem_ctx)
2762 {
2763         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2764 }
2765
2766 /*******************************************************************
2767  * fill a notify_info_data with the port name
2768  ********************************************************************/
2769
2770 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2771                                      int snum,
2772                                      struct spoolss_Notify *data,
2773                                      print_queue_struct *queue,
2774                                      struct spoolss_PrinterInfo2 *pinfo2,
2775                                      TALLOC_CTX *mem_ctx)
2776 {
2777         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2778 }
2779
2780 /*******************************************************************
2781  * fill a notify_info_data with the printername
2782  * but it doesn't exist, have to see what to do
2783  ********************************************************************/
2784
2785 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2786                                        int snum,
2787                                        struct spoolss_Notify *data,
2788                                        print_queue_struct *queue,
2789                                        struct spoolss_PrinterInfo2 *pinfo2,
2790                                        TALLOC_CTX *mem_ctx)
2791 {
2792         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2793 }
2794
2795 /*******************************************************************
2796  * fill a notify_info_data with the comment
2797  ********************************************************************/
2798
2799 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2800                                    int snum,
2801                                    struct spoolss_Notify *data,
2802                                    print_queue_struct *queue,
2803                                    struct spoolss_PrinterInfo2 *pinfo2,
2804                                    TALLOC_CTX *mem_ctx)
2805 {
2806         const char *p;
2807
2808         if (*pinfo2->comment == '\0') {
2809                 p = lp_comment(talloc_tos(), snum);
2810         } else {
2811                 p = pinfo2->comment;
2812         }
2813
2814         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2815 }
2816
2817 /*******************************************************************
2818  * fill a notify_info_data with the comment
2819  * location = "Room 1, floor 2, building 3"
2820  ********************************************************************/
2821
2822 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2823                                     int snum,
2824                                     struct spoolss_Notify *data,
2825                                     print_queue_struct *queue,
2826                                     struct spoolss_PrinterInfo2 *pinfo2,
2827                                     TALLOC_CTX *mem_ctx)
2828 {
2829         const char *loc = pinfo2->location;
2830         NTSTATUS status;
2831
2832         status = printer_list_get_printer(mem_ctx,
2833                                           pinfo2->sharename,
2834                                           NULL,
2835                                           &loc,
2836                                           NULL);
2837         if (NT_STATUS_IS_OK(status)) {
2838                 if (loc == NULL) {
2839                         loc = pinfo2->location;
2840                 }
2841         }
2842
2843         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2844 }
2845
2846 /*******************************************************************
2847  * fill a notify_info_data with the device mode
2848  * jfm:xxxx don't to it for know but that's a real problem !!!
2849  ********************************************************************/
2850
2851 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2852                                    int snum,
2853                                    struct spoolss_Notify *data,
2854                                    print_queue_struct *queue,
2855                                    struct spoolss_PrinterInfo2 *pinfo2,
2856                                    TALLOC_CTX *mem_ctx)
2857 {
2858         /* for a dummy implementation we have to zero the fields */
2859         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2860 }
2861
2862 /*******************************************************************
2863  * fill a notify_info_data with the separator file name
2864  ********************************************************************/
2865
2866 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2867                                    int snum,
2868                                    struct spoolss_Notify *data,
2869                                    print_queue_struct *queue,
2870                                    struct spoolss_PrinterInfo2 *pinfo2,
2871                                    TALLOC_CTX *mem_ctx)
2872 {
2873         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2874 }
2875
2876 /*******************************************************************
2877  * fill a notify_info_data with the print processor
2878  * jfm:xxxx return always winprint to indicate we don't do anything to it
2879  ********************************************************************/
2880
2881 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2882                                            int snum,
2883                                            struct spoolss_Notify *data,
2884                                            print_queue_struct *queue,
2885                                            struct spoolss_PrinterInfo2 *pinfo2,
2886                                            TALLOC_CTX *mem_ctx)
2887 {
2888         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2889 }
2890
2891 /*******************************************************************
2892  * fill a notify_info_data with the print processor options
2893  * jfm:xxxx send an empty string
2894  ********************************************************************/
2895
2896 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2897                                       int snum,
2898                                       struct spoolss_Notify *data,
2899                                       print_queue_struct *queue,
2900                                       struct spoolss_PrinterInfo2 *pinfo2,
2901                                       TALLOC_CTX *mem_ctx)
2902 {
2903         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2904 }
2905
2906 /*******************************************************************
2907  * fill a notify_info_data with the data type
2908  * jfm:xxxx always send RAW as data type
2909  ********************************************************************/
2910
2911 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2912                                     int snum,
2913                                     struct spoolss_Notify *data,
2914                                     print_queue_struct *queue,
2915                                     struct spoolss_PrinterInfo2 *pinfo2,
2916                                     TALLOC_CTX *mem_ctx)
2917 {
2918         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2919 }
2920
2921 /*******************************************************************
2922  * fill a notify_info_data with the security descriptor
2923  * jfm:xxxx send an null pointer to say no security desc
2924  * have to implement security before !
2925  ********************************************************************/
2926
2927 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2928                                          int snum,
2929                                          struct spoolss_Notify *data,
2930                                          print_queue_struct *queue,
2931                                          struct spoolss_PrinterInfo2 *pinfo2,
2932                                          TALLOC_CTX *mem_ctx)
2933 {
2934         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2935 }
2936
2937 /*******************************************************************
2938  * fill a notify_info_data with the attributes
2939  * jfm:xxxx a samba printer is always shared
2940  ********************************************************************/
2941
2942 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2943                                       int snum,
2944                                       struct spoolss_Notify *data,
2945                                       print_queue_struct *queue,
2946                                       struct spoolss_PrinterInfo2 *pinfo2,
2947                                       TALLOC_CTX *mem_ctx)
2948 {
2949         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2950 }
2951
2952 /*******************************************************************
2953  * fill a notify_info_data with the priority
2954  ********************************************************************/
2955
2956 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2957                                     int snum,
2958                                     struct spoolss_Notify *data,
2959                                     print_queue_struct *queue,
2960                                     struct spoolss_PrinterInfo2 *pinfo2,
2961                                     TALLOC_CTX *mem_ctx)
2962 {
2963         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2964 }
2965
2966 /*******************************************************************
2967  * fill a notify_info_data with the default priority
2968  ********************************************************************/
2969
2970 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2971                                             int snum,
2972                                             struct spoolss_Notify *data,
2973                                             print_queue_struct *queue,
2974                                             struct spoolss_PrinterInfo2 *pinfo2,
2975                                             TALLOC_CTX *mem_ctx)
2976 {
2977         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2978 }
2979
2980 /*******************************************************************
2981  * fill a notify_info_data with the start time
2982  ********************************************************************/
2983
2984 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2985                                       int snum,
2986                                       struct spoolss_Notify *data,
2987                                       print_queue_struct *queue,
2988                                       struct spoolss_PrinterInfo2 *pinfo2,
2989                                       TALLOC_CTX *mem_ctx)
2990 {
2991         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2992 }
2993
2994 /*******************************************************************
2995  * fill a notify_info_data with the until time
2996  ********************************************************************/
2997
2998 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
2999                                       int snum,
3000                                       struct spoolss_Notify *data,
3001                                       print_queue_struct *queue,
3002                                       struct spoolss_PrinterInfo2 *pinfo2,
3003                                       TALLOC_CTX *mem_ctx)
3004 {
3005         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3006 }
3007
3008 /*******************************************************************
3009  * fill a notify_info_data with the status
3010  ********************************************************************/
3011
3012 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3013                                   int snum,
3014                                   struct spoolss_Notify *data,
3015                                   print_queue_struct *queue,
3016                                   struct spoolss_PrinterInfo2 *pinfo2,
3017                                   TALLOC_CTX *mem_ctx)
3018 {
3019         print_status_struct status;
3020
3021         print_queue_length(msg_ctx, snum, &status);
3022         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3023 }
3024
3025 /*******************************************************************
3026  * fill a notify_info_data with the number of jobs queued
3027  ********************************************************************/
3028
3029 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3030                                  int snum,
3031                                  struct spoolss_Notify *data,
3032                                  print_queue_struct *queue,
3033                                  struct spoolss_PrinterInfo2 *pinfo2,
3034                                  TALLOC_CTX *mem_ctx)
3035 {
3036         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3037                 data, print_queue_length(msg_ctx, snum, NULL));
3038 }
3039
3040 /*******************************************************************
3041  * fill a notify_info_data with the average ppm
3042  ********************************************************************/
3043
3044 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3045                                        int snum,
3046                                        struct spoolss_Notify *data,
3047                                        print_queue_struct *queue,
3048                                        struct spoolss_PrinterInfo2 *pinfo2,
3049                                        TALLOC_CTX *mem_ctx)
3050 {
3051         /* always respond 8 pages per minutes */
3052         /* a little hard ! */
3053         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3054 }
3055
3056 /*******************************************************************
3057  * fill a notify_info_data with username
3058  ********************************************************************/
3059
3060 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3061                                     int snum,
3062                                     struct spoolss_Notify *data,
3063                                     print_queue_struct *queue,
3064                                     struct spoolss_PrinterInfo2 *pinfo2,
3065                                     TALLOC_CTX *mem_ctx)
3066 {
3067         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3068 }
3069
3070 /*******************************************************************
3071  * fill a notify_info_data with job status
3072  ********************************************************************/
3073
3074 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3075                                       int snum,
3076                                       struct spoolss_Notify *data,
3077                                       print_queue_struct *queue,
3078                                       struct spoolss_PrinterInfo2 *pinfo2,
3079                                       TALLOC_CTX *mem_ctx)
3080 {
3081         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3082 }
3083
3084 /*******************************************************************
3085  * fill a notify_info_data with job name
3086  ********************************************************************/
3087
3088 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3089                                     int snum,
3090                                     struct spoolss_Notify *data,
3091                                     print_queue_struct *queue,
3092                                     struct spoolss_PrinterInfo2 *pinfo2,
3093                                     TALLOC_CTX *mem_ctx)
3094 {
3095         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3096 }
3097
3098 /*******************************************************************
3099  * fill a notify_info_data with job status
3100  ********************************************************************/
3101
3102 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3103                                              int snum,
3104                                              struct spoolss_Notify *data,
3105                                              print_queue_struct *queue,
3106                                              struct spoolss_PrinterInfo2 *pinfo2,
3107                                              TALLOC_CTX *mem_ctx)
3108 {
3109         /*
3110          * Now we're returning job status codes we just return a "" here. JRA.
3111          */
3112
3113         const char *p = "";
3114
3115 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3116         p = "unknown";
3117
3118         switch (queue->status) {
3119         case LPQ_QUEUED:
3120                 p = "Queued";
3121                 break;
3122         case LPQ_PAUSED:
3123                 p = "";    /* NT provides the paused string */
3124                 break;
3125         case LPQ_SPOOLING:
3126                 p = "Spooling";
3127                 break;
3128         case LPQ_PRINTING:
3129                 p = "Printing";
3130                 break;
3131         }
3132 #endif /* NO LONGER NEEDED. */
3133
3134         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3135 }
3136
3137 /*******************************************************************
3138  * fill a notify_info_data with job time
3139  ********************************************************************/
3140
3141 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3142                                     int snum,
3143                                     struct spoolss_Notify *data,
3144                                     print_queue_struct *queue,
3145                                     struct spoolss_PrinterInfo2 *pinfo2,
3146                                     TALLOC_CTX *mem_ctx)
3147 {
3148         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3149 }
3150
3151 /*******************************************************************
3152  * fill a notify_info_data with job size
3153  ********************************************************************/
3154
3155 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3156                                     int snum,
3157                                     struct spoolss_Notify *data,
3158                                     print_queue_struct *queue,
3159                                     struct spoolss_PrinterInfo2 *pinfo2,
3160                                     TALLOC_CTX *mem_ctx)
3161 {
3162         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3163 }
3164
3165 /*******************************************************************
3166  * fill a notify_info_data with page info
3167  ********************************************************************/
3168 static void spoolss_notify_total_pages(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, queue->page_count);
3176 }
3177
3178 /*******************************************************************
3179  * fill a notify_info_data with pages printed info.
3180  ********************************************************************/
3181 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3182                                          int snum,
3183                                 struct spoolss_Notify *data,
3184                                 print_queue_struct *queue,
3185                                 struct spoolss_PrinterInfo2 *pinfo2,
3186                                 TALLOC_CTX *mem_ctx)
3187 {
3188         /* Add code when back-end tracks this */
3189         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3190 }
3191
3192 /*******************************************************************
3193  Fill a notify_info_data with job position.
3194  ********************************************************************/
3195
3196 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3197                                         int snum,
3198                                         struct spoolss_Notify *data,
3199                                         print_queue_struct *queue,
3200                                         struct spoolss_PrinterInfo2 *pinfo2,
3201                                         TALLOC_CTX *mem_ctx)
3202 {
3203         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3204 }
3205
3206 /*******************************************************************
3207  Fill a notify_info_data with submitted time.
3208  ********************************************************************/
3209
3210 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3211                                           int snum,
3212                                           struct spoolss_Notify *data,
3213                                           print_queue_struct *queue,
3214                                           struct spoolss_PrinterInfo2 *pinfo2,
3215                                           TALLOC_CTX *mem_ctx)
3216 {
3217         data->data.string.string = NULL;
3218         data->data.string.size = 0;
3219
3220         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3221                                &data->data.string.string,
3222                                &data->data.string.size);
3223
3224 }
3225
3226 struct s_notify_info_data_table
3227 {
3228         enum spoolss_NotifyType type;
3229         uint16_t field;
3230         const char *name;
3231         enum spoolss_NotifyTable variable_type;
3232         void (*fn) (struct messaging_context *msg_ctx,
3233                     int snum, struct spoolss_Notify *data,
3234                     print_queue_struct *queue,
3235                     struct spoolss_PrinterInfo2 *pinfo2,
3236                     TALLOC_CTX *mem_ctx);
3237 };
3238
3239 /* A table describing the various print notification constants and
3240    whether the notification data is a pointer to a variable sized
3241    buffer, a one value uint32_t or a two value uint32_t. */
3242
3243 static const struct s_notify_info_data_table notify_info_data_table[] =
3244 {
3245 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3246 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3247 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3248 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3249 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3250 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3251 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3252 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3253 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3254 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3271 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3272 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3273 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3274 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3275 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3276 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3277 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3278 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3279 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3280 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3281 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3282 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3283 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3284 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3285 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3286 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3287 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3288 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3289 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3290 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3291 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3292 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3293 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3294 };
3295
3296 /*******************************************************************
3297  Return the variable_type of info_data structure.
3298 ********************************************************************/
3299
3300 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3301                                                                   uint16_t field)
3302 {
3303         int i=0;
3304
3305         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3306                 if ( (notify_info_data_table[i].type == type) &&
3307                      (notify_info_data_table[i].field == field) ) {
3308                         return notify_info_data_table[i].variable_type;
3309                 }
3310         }
3311
3312         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3313
3314         return (enum spoolss_NotifyTable) 0;
3315 }
3316
3317 /****************************************************************************
3318 ****************************************************************************/
3319
3320 static bool search_notify(enum spoolss_NotifyType type,
3321                           uint16_t field,
3322                           int *value)
3323 {
3324         int i;
3325
3326         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3327                 if (notify_info_data_table[i].type == type &&
3328                     notify_info_data_table[i].field == field &&
3329                     notify_info_data_table[i].fn != NULL) {
3330                         *value = i;
3331                         return true;
3332                 }
3333         }
3334
3335         return false;
3336 }
3337
3338 /****************************************************************************
3339 ****************************************************************************/
3340
3341 static void construct_info_data(struct spoolss_Notify *info_data,
3342                                 enum spoolss_NotifyType type,
3343                                 uint16_t field, int id)
3344 {
3345         info_data->type                 = type;
3346         info_data->field.field          = field;
3347         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3348         info_data->job_id               = id;
3349 }
3350
3351 /*******************************************************************
3352  *
3353  * fill a notify_info struct with info asked
3354  *
3355  ********************************************************************/
3356
3357 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3358                                           struct printer_handle *print_hnd,
3359                                           struct spoolss_NotifyInfo *info,
3360                                           struct spoolss_PrinterInfo2 *pinfo2,
3361                                           int snum,
3362                                           const struct spoolss_NotifyOptionType *option_type,
3363                                           uint32_t id,
3364                                           TALLOC_CTX *mem_ctx)
3365 {
3366         int field_num,j;
3367         enum spoolss_NotifyType type;
3368         uint16_t field;
3369
3370         struct spoolss_Notify *current_data;
3371
3372         type = option_type->type;
3373
3374         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3375                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3376                 option_type->count, lp_servicename(talloc_tos(), snum)));
3377
3378         for(field_num=0; field_num < option_type->count; field_num++) {
3379                 field = option_type->fields[field_num].field;
3380
3381                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3382
3383                 if (!search_notify(type, field, &j) )
3384                         continue;
3385
3386                 info->notifies = talloc_realloc(info, info->notifies,
3387                                                       struct spoolss_Notify,
3388                                                       info->count + 1);
3389                 if (info->notifies == NULL) {
3390                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3391                         return false;
3392                 }
3393
3394                 current_data = &info->notifies[info->count];
3395
3396                 construct_info_data(current_data, type, field, id);
3397
3398                 DEBUG(10, ("construct_notify_printer_info: "
3399                            "calling [%s]  snum=%d  printername=[%s])\n",
3400                            notify_info_data_table[j].name, snum,
3401                            pinfo2->printername));
3402
3403                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3404                                              NULL, pinfo2, mem_ctx);
3405
3406                 info->count++;
3407         }
3408
3409         return true;
3410 }
3411
3412 /*******************************************************************
3413  *
3414  * fill a notify_info struct with info asked
3415  *
3416  ********************************************************************/
3417
3418 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3419                                        print_queue_struct *queue,
3420                                        struct spoolss_NotifyInfo *info,
3421                                        struct spoolss_PrinterInfo2 *pinfo2,
3422                                        int snum,
3423                                        const struct spoolss_NotifyOptionType *option_type,
3424                                        uint32_t id,
3425                                        TALLOC_CTX *mem_ctx)
3426 {
3427         int field_num,j;
3428         enum spoolss_NotifyType type;
3429         uint16_t field;
3430         struct spoolss_Notify *current_data;
3431
3432         DEBUG(4,("construct_notify_jobs_info\n"));
3433
3434         type = option_type->type;
3435
3436         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3437                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3438                 option_type->count));
3439
3440         for(field_num=0; field_num<option_type->count; field_num++) {
3441                 field = option_type->fields[field_num].field;
3442
3443                 if (!search_notify(type, field, &j) )
3444                         continue;
3445
3446                 info->notifies = talloc_realloc(info, info->notifies,
3447                                                       struct spoolss_Notify,
3448                                                       info->count + 1);
3449                 if (info->notifies == NULL) {
3450                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3451                         return false;
3452                 }
3453
3454                 current_data=&(info->notifies[info->count]);
3455
3456                 construct_info_data(current_data, type, field, id);
3457                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3458                                              queue, pinfo2, mem_ctx);
3459                 info->count++;
3460         }
3461
3462         return true;
3463 }
3464
3465 /*
3466  * JFM: The enumeration is not that simple, it's even non obvious.
3467  *
3468  * let's take an example: I want to monitor the PRINTER SERVER for
3469  * the printer's name and the number of jobs currently queued.
3470  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3471  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3472  *
3473  * I have 3 printers on the back of my server.
3474  *
3475  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3476  * structures.
3477  *   Number     Data                    Id
3478  *      1       printer 1 name          1
3479  *      2       printer 1 cjob          1
3480  *      3       printer 2 name          2
3481  *      4       printer 2 cjob          2
3482  *      5       printer 3 name          3
3483  *      6       printer 3 name          3
3484  *
3485  * that's the print server case, the printer case is even worse.
3486  */
3487
3488 /*******************************************************************
3489  *
3490  * enumerate all printers on the printserver
3491  * fill a notify_info struct with info asked
3492  *
3493  ********************************************************************/
3494
3495 static WERROR printserver_notify_info(struct pipes_struct *p,
3496                                       struct policy_handle *hnd,
3497                                       struct spoolss_NotifyInfo *info,
3498                                       TALLOC_CTX *mem_ctx)
3499 {
3500         int snum;
3501         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3502         int n_services=lp_numservices();
3503         int i;
3504         struct spoolss_NotifyOption *option;
3505         struct spoolss_NotifyOptionType option_type;
3506         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3507         WERROR result;
3508
3509         DEBUG(4,("printserver_notify_info\n"));
3510
3511         if (!Printer)
3512                 return WERR_BADFID;
3513
3514         option = Printer->notify.option;
3515
3516         info->version   = 2;
3517         info->notifies  = NULL;
3518         info->count     = 0;
3519
3520         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3521            sending a ffpcn() request first */
3522
3523         if ( !option )
3524                 return WERR_BADFID;
3525
3526         for (i=0; i<option->count; i++) {
3527                 option_type = option->types[i];
3528
3529                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3530                         continue;
3531
3532                 for (snum = 0; snum < n_services; snum++) {
3533                         if (!lp_browseable(snum) ||
3534                             !lp_snum_ok(snum) ||
3535                             !lp_print_ok(snum)) {
3536                                 continue; /* skip */
3537                         }
3538
3539                         /* Maybe we should use the SYSTEM session_info here... */
3540                         result = winreg_get_printer_internal(mem_ctx,
3541                                                     get_session_info_system(),
3542                                                     p->msg_ctx,
3543                                                     lp_servicename(talloc_tos(), snum),
3544                                                     &pinfo2);
3545                         if (!W_ERROR_IS_OK(result)) {
3546                                 DEBUG(4, ("printserver_notify_info: "
3547                                           "Failed to get printer [%s]\n",
3548                                           lp_servicename(talloc_tos(), snum)));
3549                                 continue;
3550                         }
3551
3552
3553                         construct_notify_printer_info(p->msg_ctx,
3554                                                       Printer, info,
3555                                                       pinfo2, snum,
3556                                                       &option_type, snum,
3557                                                       mem_ctx);
3558
3559                         TALLOC_FREE(pinfo2);
3560                 }
3561         }
3562
3563 #if 0
3564         /*
3565          * Debugging information, don't delete.
3566          */
3567
3568         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3569         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3570         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3571
3572         for (i=0; i<info->count; i++) {
3573                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3574                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3575                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3576         }
3577 #endif
3578
3579         return WERR_OK;
3580 }
3581
3582 /*******************************************************************
3583  *
3584  * fill a notify_info struct with info asked
3585  *
3586  ********************************************************************/
3587
3588 static WERROR printer_notify_info(struct pipes_struct *p,
3589                                   struct policy_handle *hnd,
3590                                   struct spoolss_NotifyInfo *info,
3591                                   TALLOC_CTX *mem_ctx)
3592 {
3593         int snum;
3594         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3595         int i;
3596         uint32_t id;
3597         struct spoolss_NotifyOption *option;
3598         struct spoolss_NotifyOptionType option_type;
3599         int count,j;
3600         print_queue_struct *queue=NULL;
3601         print_status_struct status;
3602         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3603         WERROR result;
3604
3605         DEBUG(4,("printer_notify_info\n"));
3606
3607         if (!Printer)
3608                 return WERR_BADFID;
3609
3610         option = Printer->notify.option;
3611         id = 0x0;
3612
3613         info->version   = 2;
3614         info->notifies  = NULL;
3615         info->count     = 0;
3616
3617         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3618            sending a ffpcn() request first */
3619
3620         if ( !option )
3621                 return WERR_BADFID;
3622
3623         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3624                 return WERR_BADFID;
3625         }
3626
3627         /* Maybe we should use the SYSTEM session_info here... */
3628         result = winreg_get_printer_internal(mem_ctx,
3629                                     get_session_info_system(),
3630                                     p->msg_ctx,
3631                                     lp_servicename(talloc_tos(), snum), &pinfo2);
3632         if (!W_ERROR_IS_OK(result)) {
3633                 return WERR_BADFID;
3634         }
3635
3636         /*
3637          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3638          * correct servername.
3639          */
3640         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3641         if (pinfo2->servername == NULL) {
3642                 return WERR_NOMEM;
3643         }
3644
3645         for (i=0; i<option->count; i++) {
3646                 option_type = option->types[i];
3647
3648                 switch (option_type.type) {
3649                 case PRINTER_NOTIFY_TYPE:
3650                         if (construct_notify_printer_info(p->msg_ctx,
3651                                                           Printer, info,
3652                                                           pinfo2, snum,
3653                                                           &option_type, id,
3654                                                           mem_ctx)) {
3655                                 id--;
3656                         }
3657                         break;
3658
3659                 case JOB_NOTIFY_TYPE:
3660
3661                         count = print_queue_status(p->msg_ctx, snum, &queue,
3662                                                    &status);
3663
3664                         for (j=0; j<count; j++) {
3665                                 construct_notify_jobs_info(p->msg_ctx,
3666                                                            &queue[j], info,
3667                                                            pinfo2, snum,
3668                                                            &option_type,
3669                                                            queue[j].sysjob,
3670                                                            mem_ctx);
3671                         }
3672
3673                         SAFE_FREE(queue);
3674                         break;
3675                 }
3676         }
3677
3678         /*
3679          * Debugging information, don't delete.
3680          */
3681         /*
3682         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3683         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3684         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3685
3686         for (i=0; i<info->count; i++) {
3687                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3688                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3689                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3690         }
3691         */
3692
3693         talloc_free(pinfo2);
3694         return WERR_OK;
3695 }
3696
3697 /****************************************************************
3698  _spoolss_RouterRefreshPrinterChangeNotify
3699 ****************************************************************/
3700
3701 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3702                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3703 {
3704         struct spoolss_NotifyInfo *info;
3705
3706         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3707         WERROR result = WERR_BADFID;
3708
3709         /* we always have a spoolss_NotifyInfo struct */
3710         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3711         if (!info) {
3712                 result = WERR_NOMEM;
3713                 goto done;
3714         }
3715
3716         *r->out.info = info;
3717
3718         if (!Printer) {
3719                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3720                         "Invalid handle (%s:%u:%u).\n",
3721                         OUR_HANDLE(r->in.handle)));
3722                 goto done;
3723         }
3724
3725         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3726
3727         /*
3728          *      We are now using the change value, and
3729          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3730          *      I don't have a global notification system, I'm sending back all the
3731          *      information even when _NOTHING_ has changed.
3732          */
3733
3734         /* We need to keep track of the change value to send back in
3735            RRPCN replies otherwise our updates are ignored. */
3736
3737         Printer->notify.fnpcn = true;
3738
3739         if (Printer->notify.cli_chan != NULL &&
3740             Printer->notify.cli_chan->active_connections > 0) {
3741                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3742                         "Saving change value in request [%x]\n",
3743                         r->in.change_low));
3744                 Printer->notify.change = r->in.change_low;
3745         }
3746
3747         /* just ignore the spoolss_NotifyOption */
3748
3749         switch (Printer->printer_type) {
3750                 case SPLHND_SERVER:
3751                         result = printserver_notify_info(p, r->in.handle,
3752                                                          info, p->mem_ctx);
3753                         break;
3754
3755                 case SPLHND_PRINTER:
3756                         result = printer_notify_info(p, r->in.handle,
3757                                                      info, p->mem_ctx);
3758                         break;
3759         }
3760
3761         Printer->notify.fnpcn = false;
3762
3763 done:
3764         return result;
3765 }
3766
3767 /********************************************************************
3768  ********************************************************************/
3769
3770 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3771                                  const char *servername,
3772                                  const char *printername,
3773                                  const char **printername_p)
3774 {
3775         /* FIXME: add lp_force_printername() */
3776
3777         if (servername == NULL) {
3778                 *printername_p = talloc_strdup(mem_ctx, printername);
3779                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3780                 return WERR_OK;
3781         }
3782
3783         if (servername[0] == '\\' && servername[1] == '\\') {
3784                 servername += 2;
3785         }
3786
3787         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3788         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3789
3790         return WERR_OK;
3791 }
3792
3793 /********************************************************************
3794  ********************************************************************/
3795
3796 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3797                                           const char *printername)
3798 {
3799         if (dm == NULL) {
3800                 return;
3801         }
3802
3803         dm->devicename = talloc_strndup(dm, printername,
3804                                         MIN(strlen(printername), 31));
3805 }
3806
3807 /********************************************************************
3808  * construct_printer_info_0
3809  * fill a printer_info_0 struct
3810  ********************************************************************/
3811
3812 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3813                                       const struct auth_session_info *session_info,
3814                                       struct messaging_context *msg_ctx,
3815                                       struct spoolss_PrinterInfo2 *info2,
3816                                       const char *servername,
3817                                       struct spoolss_PrinterInfo0 *r,
3818                                       int snum)
3819 {
3820         int count;
3821         struct printer_session_counter *session_counter;
3822         struct timeval setuptime;
3823         print_status_struct status;
3824         WERROR result;
3825
3826         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3827         if (!W_ERROR_IS_OK(result)) {
3828                 return result;
3829         }
3830
3831         if (servername) {
3832                 r->servername = talloc_strdup(mem_ctx, servername);
3833                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3834         } else {
3835                 r->servername = NULL;
3836         }
3837
3838         count = print_queue_length(msg_ctx, snum, &status);
3839
3840         /* check if we already have a counter for this printer */
3841         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3842                 if (session_counter->snum == snum)
3843                         break;
3844         }
3845
3846         /* it's the first time, add it to the list */
3847         if (session_counter == NULL) {
3848                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3849                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3850                 session_counter->snum           = snum;
3851                 session_counter->counter        = 0;
3852                 DLIST_ADD(counter_list, session_counter);
3853         }
3854
3855         /* increment it */
3856         session_counter->counter++;
3857
3858         r->cjobs                        = count;
3859         r->total_jobs                   = 0;
3860         r->total_bytes                  = 0;
3861
3862         get_startup_time(&setuptime);
3863         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3864
3865         /* JFM:
3866          * the global_counter should be stored in a TDB as it's common to all the clients
3867          * and should be zeroed on samba startup
3868          */
3869         r->global_counter               = session_counter->counter;
3870         r->total_pages                  = 0;
3871         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3872         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3873         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3874         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3875         r->spooling                     = 0;
3876         r->max_spooling                 = 0;
3877         r->session_counter              = session_counter->counter;
3878         r->num_error_out_of_paper       = 0x0;
3879         r->num_error_not_ready          = 0x0;          /* number of print failure */
3880         r->job_error                    = 0x0;
3881         r->number_of_processors         = 0x1;
3882         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3883         r->high_part_total_bytes        = 0x0;
3884
3885         /* ChangeID in milliseconds*/
3886         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3887                                     info2->sharename, &r->change_id);
3888
3889         r->last_error                   = WERR_OK;
3890         r->status                       = nt_printq_status(status.status);
3891         r->enumerate_network_printers   = 0x0;
3892         r->c_setprinter                 = 0x0;
3893         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3894         r->processor_level              = 0x6;          /* 6  ???*/
3895         r->ref_ic                       = 0;
3896         r->reserved2                    = 0;
3897         r->reserved3                    = 0;
3898
3899         return WERR_OK;
3900 }
3901
3902
3903 /********************************************************************
3904  * construct_printer_info1
3905  * fill a spoolss_PrinterInfo1 struct
3906 ********************************************************************/
3907
3908 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3909                                       const struct spoolss_PrinterInfo2 *info2,
3910                                       uint32_t flags,
3911                                       const char *servername,
3912                                       struct spoolss_PrinterInfo1 *r,
3913                                       int snum)
3914 {
3915         WERROR result;
3916
3917         r->flags                = flags;
3918
3919         if (info2->comment == NULL || info2->comment[0] == '\0') {
3920                 r->comment      = lp_comment(mem_ctx, snum);
3921         } else {
3922                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3923         }
3924         W_ERROR_HAVE_NO_MEMORY(r->comment);
3925
3926         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3927         if (!W_ERROR_IS_OK(result)) {
3928                 return result;
3929         }
3930
3931         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3932                                                   r->name,
3933                                                   info2->drivername,
3934                                                   r->comment);
3935         W_ERROR_HAVE_NO_MEMORY(r->description);
3936
3937         return WERR_OK;
3938 }
3939
3940 /********************************************************************
3941  * construct_printer_info2
3942  * fill a spoolss_PrinterInfo2 struct
3943 ********************************************************************/
3944
3945 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3946                                       struct messaging_context *msg_ctx,
3947                                       const struct spoolss_PrinterInfo2 *info2,
3948                                       const char *servername,
3949                                       struct spoolss_PrinterInfo2 *r,
3950                                       int snum)
3951 {
3952         int count;
3953         print_status_struct status;
3954         WERROR result;
3955
3956         count = print_queue_length(msg_ctx, snum, &status);
3957
3958         if (servername) {
3959                 r->servername           = talloc_strdup(mem_ctx, servername);
3960                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3961         } else {
3962                 r->servername           = NULL;
3963         }
3964
3965         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3966         if (!W_ERROR_IS_OK(result)) {
3967                 return result;
3968         }
3969
3970         r->sharename            = lp_servicename(mem_ctx, snum);
3971         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3972         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3973         W_ERROR_HAVE_NO_MEMORY(r->portname);
3974         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3975         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3976
3977         if (info2->comment[0] == '\0') {
3978                 r->comment      = lp_comment(mem_ctx, snum);
3979         } else {
3980                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
3981         }
3982         W_ERROR_HAVE_NO_MEMORY(r->comment);
3983
3984         r->location     = talloc_strdup(mem_ctx, info2->location);
3985         if (info2->location[0] == '\0') {
3986                 const char *loc = NULL;
3987                 NTSTATUS nt_status;
3988
3989                 nt_status = printer_list_get_printer(mem_ctx,
3990                                                      info2->sharename,
3991                                                      NULL,
3992                                                      &loc,
3993                                                      NULL);
3994                 if (NT_STATUS_IS_OK(nt_status)) {
3995                         if (loc != NULL) {
3996                                 r->location = talloc_strdup(mem_ctx, loc);
3997                         }
3998                 }
3999         }
4000         W_ERROR_HAVE_NO_MEMORY(r->location);
4001
4002         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4003         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4004         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4005         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4006         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4007         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4008         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4009         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4010
4011         r->attributes           = info2->attributes;
4012
4013         r->priority             = info2->priority;
4014         r->defaultpriority      = info2->defaultpriority;
4015         r->starttime            = info2->starttime;
4016         r->untiltime            = info2->untiltime;
4017         r->status               = nt_printq_status(status.status);
4018         r->cjobs                = count;
4019         r->averageppm           = info2->averageppm;
4020
4021         if (info2->devmode != NULL) {
4022                 result = copy_devicemode(mem_ctx,
4023                                          info2->devmode,
4024                                          &r->devmode);
4025                 if (!W_ERROR_IS_OK(result)) {
4026                         return result;
4027                 }
4028         } else if (lp_default_devmode(snum)) {
4029                 result = spoolss_create_default_devmode(mem_ctx,
4030                                                         info2->printername,
4031                                                         &r->devmode);
4032                 if (!W_ERROR_IS_OK(result)) {
4033                         return result;
4034                 }
4035         } else {
4036                 r->devmode = NULL;
4037                 DEBUG(8,("Returning NULL Devicemode!\n"));
4038         }
4039
4040         compose_devicemode_devicename(r->devmode, r->printername);
4041
4042         r->secdesc = NULL;
4043
4044         if (info2->secdesc != NULL) {
4045                 /* don't use talloc_steal() here unless you do a deep steal of all
4046                    the SEC_DESC members */
4047
4048                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4049         }
4050
4051         return WERR_OK;
4052 }
4053
4054 /********************************************************************
4055  * construct_printer_info3
4056  * fill a spoolss_PrinterInfo3 struct
4057  ********************************************************************/
4058
4059 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4060                                       const struct spoolss_PrinterInfo2 *info2,
4061                                       const char *servername,
4062                                       struct spoolss_PrinterInfo3 *r,
4063                                       int snum)
4064 {
4065         /* These are the components of the SD we are returning. */
4066
4067         if (info2->secdesc != NULL) {
4068                 /* don't use talloc_steal() here unless you do a deep steal of all
4069                    the SEC_DESC members */
4070
4071                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4072                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4073         }
4074
4075         return WERR_OK;
4076 }
4077
4078 /********************************************************************
4079  * construct_printer_info4
4080  * fill a spoolss_PrinterInfo4 struct
4081  ********************************************************************/
4082
4083 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4084                                       const struct spoolss_PrinterInfo2 *info2,
4085                                       const char *servername,
4086                                       struct spoolss_PrinterInfo4 *r,
4087                                       int snum)
4088 {
4089         WERROR result;
4090
4091         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4092         if (!W_ERROR_IS_OK(result)) {
4093                 return result;
4094         }
4095
4096         if (servername) {
4097                 r->servername   = talloc_strdup(mem_ctx, servername);
4098                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4099         } else {
4100                 r->servername = NULL;
4101         }
4102
4103         r->attributes   = info2->attributes;
4104
4105         return WERR_OK;
4106 }
4107
4108 /********************************************************************
4109  * construct_printer_info5
4110  * fill a spoolss_PrinterInfo5 struct
4111  ********************************************************************/
4112
4113 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4114                                       const struct spoolss_PrinterInfo2 *info2,
4115                                       const char *servername,
4116                                       struct spoolss_PrinterInfo5 *r,
4117                                       int snum)
4118 {
4119         WERROR result;
4120
4121         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4122         if (!W_ERROR_IS_OK(result)) {
4123                 return result;
4124         }
4125
4126         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4127         W_ERROR_HAVE_NO_MEMORY(r->portname);
4128
4129         r->attributes   = info2->attributes;
4130
4131         /* these two are not used by NT+ according to MSDN */
4132         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4133         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4134
4135         return WERR_OK;
4136 }
4137
4138 /********************************************************************
4139  * construct_printer_info_6
4140  * fill a spoolss_PrinterInfo6 struct
4141  ********************************************************************/
4142
4143 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4144                                       struct messaging_context *msg_ctx,
4145                                       const struct spoolss_PrinterInfo2 *info2,
4146                                       const char *servername,
4147                                       struct spoolss_PrinterInfo6 *r,
4148                                       int snum)
4149 {
4150         print_status_struct status;
4151
4152         print_queue_length(msg_ctx, snum, &status);
4153
4154         r->status = nt_printq_status(status.status);
4155
4156         return WERR_OK;
4157 }
4158
4159 /********************************************************************
4160  * construct_printer_info7
4161  * fill a spoolss_PrinterInfo7 struct
4162  ********************************************************************/
4163
4164 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4165                                       struct messaging_context *msg_ctx,
4166                                       const char *servername,
4167                                       struct spoolss_PrinterInfo7 *r,
4168                                       int snum)
4169 {
4170         const struct auth_session_info *session_info = get_session_info_system();
4171         struct GUID guid;
4172
4173         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4174                                  servername,
4175                                  lp_servicename(talloc_tos(), snum), &guid, NULL)) {
4176                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4177                 r->action = DSPRINT_PUBLISH;
4178         } else {
4179                 r->guid = talloc_strdup(mem_ctx, "");
4180                 r->action = DSPRINT_UNPUBLISH;
4181         }
4182         W_ERROR_HAVE_NO_MEMORY(r->guid);
4183
4184         return WERR_OK;
4185 }
4186
4187 /********************************************************************
4188  * construct_printer_info8
4189  * fill a spoolss_PrinterInfo8 struct
4190  ********************************************************************/
4191
4192 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4193                                       const struct spoolss_PrinterInfo2 *info2,
4194                                       const char *servername,
4195                                       struct spoolss_DeviceModeInfo *r,
4196                                       int snum)
4197 {
4198         WERROR result;
4199         const char *printername;
4200
4201         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4202         if (!W_ERROR_IS_OK(result)) {
4203                 return result;
4204         }
4205
4206         if (info2->devmode != NULL) {
4207                 result = copy_devicemode(mem_ctx,
4208                                          info2->devmode,
4209                                          &r->devmode);
4210                 if (!W_ERROR_IS_OK(result)) {
4211                         return result;
4212                 }
4213         } else if (lp_default_devmode(snum)) {
4214                 result = spoolss_create_default_devmode(mem_ctx,
4215                                                         info2->printername,
4216                                                         &r->devmode);
4217                 if (!W_ERROR_IS_OK(result)) {
4218                         return result;
4219                 }
4220         } else {
4221                 r->devmode = NULL;
4222                 DEBUG(8,("Returning NULL Devicemode!\n"));
4223         }
4224
4225         compose_devicemode_devicename(r->devmode, printername);
4226
4227         return WERR_OK;
4228 }
4229
4230
4231 /********************************************************************
4232 ********************************************************************/
4233
4234 static bool snum_is_shared_printer(int snum)
4235 {
4236         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4237 }
4238
4239 /********************************************************************
4240  Spoolss_enumprinters.
4241 ********************************************************************/
4242
4243 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4244                                            const struct auth_session_info *session_info,
4245                                            struct messaging_context *msg_ctx,
4246                                            const char *servername,
4247                                            uint32_t level,
4248                                            uint32_t flags,
4249                                            union spoolss_PrinterInfo **info_p,
4250                                            uint32_t *count_p)
4251 {
4252         int snum;
4253         int n_services = lp_numservices();
4254         union spoolss_PrinterInfo *info = NULL;
4255         uint32_t count = 0;
4256         WERROR result = WERR_OK;
4257         struct dcerpc_binding_handle *b = NULL;
4258         TALLOC_CTX *tmp_ctx = NULL;
4259
4260         tmp_ctx = talloc_new(mem_ctx);
4261         if (!tmp_ctx) {
4262                 return WERR_NOMEM;
4263         }
4264
4265         *count_p = 0;
4266         *info_p = NULL;
4267
4268         for (snum = 0; snum < n_services; snum++) {
4269
4270                 const char *printer;
4271                 struct spoolss_PrinterInfo2 *info2;
4272
4273                 if (!snum_is_shared_printer(snum)) {
4274                         continue;
4275                 }
4276
4277                 printer = lp_const_servicename(snum);
4278
4279                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4280                         printer, snum));
4281
4282                 if (b == NULL) {
4283                         result = winreg_printer_binding_handle(tmp_ctx,
4284                                                                session_info,
4285                                                                msg_ctx,
4286                                                                &b);
4287                         if (!W_ERROR_IS_OK(result)) {
4288                                 goto out;
4289                         }
4290                 }
4291
4292                 result = winreg_create_printer(tmp_ctx, b,
4293                                                printer);
4294                 if (!W_ERROR_IS_OK(result)) {
4295                         goto out;
4296                 }
4297
4298                 info = talloc_realloc(tmp_ctx, info,
4299                                             union spoolss_PrinterInfo,
4300                                             count + 1);
4301                 if (!info) {
4302                         result = WERR_NOMEM;
4303                         goto out;
4304                 }
4305
4306                 result = winreg_get_printer(tmp_ctx, b,
4307                                             printer, &info2);
4308                 if (!W_ERROR_IS_OK(result)) {
4309                         goto out;
4310                 }
4311
4312                 switch (level) {
4313                 case 0:
4314                         result = construct_printer_info0(info, session_info,
4315                                                          msg_ctx, info2,
4316                                                          servername,
4317                                                          &info[count].info0, snum);
4318                         break;
4319                 case 1:
4320                         result = construct_printer_info1(info, info2, flags,
4321                                                          servername,
4322                                                          &info[count].info1, snum);
4323                         break;
4324                 case 2:
4325                         result = construct_printer_info2(info, msg_ctx, info2,
4326                                                          servername,
4327                                                          &info[count].info2, snum);
4328                         break;
4329                 case 4:
4330                         result = construct_printer_info4(info, info2,
4331                                                          servername,
4332                                                          &info[count].info4, snum);
4333                         break;
4334                 case 5:
4335                         result = construct_printer_info5(info, info2,
4336                                                          servername,
4337                                                          &info[count].info5, snum);
4338                         break;
4339
4340                 default:
4341                         result = WERR_UNKNOWN_LEVEL;
4342                         goto out;
4343                 }
4344
4345                 if (!W_ERROR_IS_OK(result)) {
4346                         goto out;
4347                 }
4348
4349                 count++;
4350         }
4351
4352 out:
4353         if (W_ERROR_IS_OK(result)) {
4354                 *info_p = talloc_move(mem_ctx, &info);
4355                 *count_p = count;
4356         }
4357
4358         talloc_free(tmp_ctx);
4359
4360         return result;
4361 }
4362
4363 /********************************************************************
4364  * handle enumeration of printers at level 0
4365  ********************************************************************/
4366
4367 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4368                                   const struct auth_session_info *session_info,
4369                                   struct messaging_context *msg_ctx,
4370                                   uint32_t flags,
4371                                   const char *servername,
4372                                   union spoolss_PrinterInfo **info,
4373                                   uint32_t *count)
4374 {
4375         DEBUG(4,("enum_all_printers_info_0\n"));
4376
4377         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4378                                             servername, 0, flags, info, count);
4379 }
4380
4381
4382 /********************************************************************
4383 ********************************************************************/
4384
4385 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4386                                        const struct auth_session_info *session_info,
4387                                        struct messaging_context *msg_ctx,
4388                                        const char *servername,
4389                                        uint32_t flags,
4390                                        union spoolss_PrinterInfo **info,
4391                                        uint32_t *count)
4392 {
4393         DEBUG(4,("enum_all_printers_info_1\n"));
4394
4395         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4396                                             servername, 1, flags, info, count);
4397 }
4398
4399 /********************************************************************
4400  enum_all_printers_info_1_local.
4401 *********************************************************************/
4402
4403 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4404                                              const struct auth_session_info *session_info,
4405                                              struct messaging_context *msg_ctx,
4406                                              const char *servername,
4407                                              union spoolss_PrinterInfo **info,
4408                                              uint32_t *count)
4409 {
4410         DEBUG(4,("enum_all_printers_info_1_local\n"));
4411
4412         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4413                                         servername, PRINTER_ENUM_ICON8, info, count);
4414 }
4415
4416 /********************************************************************
4417  enum_all_printers_info_1_name.
4418 *********************************************************************/
4419
4420 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4421                                             const struct auth_session_info *session_info,
4422                                             struct messaging_context *msg_ctx,
4423                                             const char *servername,
4424                                             union spoolss_PrinterInfo **info,
4425                                             uint32_t *count)
4426 {
4427         const char *s = servername;
4428
4429         DEBUG(4,("enum_all_printers_info_1_name\n"));
4430
4431         if (servername != NULL &&
4432             (servername[0] == '\\') && (servername[1] == '\\')) {
4433                 s = servername + 2;
4434         }
4435
4436         if (!is_myname_or_ipaddr(s)) {
4437                 return WERR_INVALID_NAME;
4438         }
4439
4440         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4441                                         servername, PRINTER_ENUM_ICON8, info, count);
4442 }
4443
4444 /********************************************************************
4445  enum_all_printers_info_1_network.
4446 *********************************************************************/
4447
4448 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4449                                                const struct auth_session_info *session_info,
4450                                                struct messaging_context *msg_ctx,
4451                                                const char *servername,
4452                                                union spoolss_PrinterInfo **info,
4453                                                uint32_t *count)
4454 {
4455         const char *s = servername;
4456
4457         DEBUG(4,("enum_all_printers_info_1_network\n"));
4458
4459         /* If we respond to a enum_printers level 1 on our name with flags
4460            set to PRINTER_ENUM_REMOTE with a list of printers then these
4461            printers incorrectly appear in the APW browse list.
4462            Specifically the printers for the server appear at the workgroup
4463            level where all the other servers in the domain are
4464            listed. Windows responds to this call with a
4465            WERR_CAN_NOT_COMPLETE so we should do the same. */
4466
4467         if (servername[0] == '\\' && servername[1] == '\\') {
4468                  s = servername + 2;
4469         }
4470
4471         if (is_myname_or_ipaddr(s)) {
4472                  return WERR_CAN_NOT_COMPLETE;
4473         }
4474
4475         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4476                                         servername, PRINTER_ENUM_NAME, info, count);
4477 }
4478
4479 /********************************************************************
4480  * api_spoolss_enumprinters
4481  *
4482  * called from api_spoolss_enumprinters (see this to understand)
4483  ********************************************************************/
4484
4485 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4486                                        const struct auth_session_info *session_info,
4487                                        struct messaging_context *msg_ctx,
4488                                        const char *servername,
4489                                        union spoolss_PrinterInfo **info,
4490                                        uint32_t *count)
4491 {
4492         DEBUG(4,("enum_all_printers_info_2\n"));
4493
4494         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4495                                             servername, 2, 0, info, count);
4496 }
4497
4498 /********************************************************************
4499  * handle enumeration of printers at level 1
4500  ********************************************************************/
4501
4502 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4503                                   const struct auth_session_info *session_info,
4504                                   struct messaging_context *msg_ctx,
4505                                   uint32_t flags,
4506                                   const char *servername,
4507                                   union spoolss_PrinterInfo **info,
4508                                   uint32_t *count)
4509 {
4510         /* Not all the flags are equals */
4511
4512         if (flags & PRINTER_ENUM_LOCAL) {
4513                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4514                                                       msg_ctx, servername, info, count);
4515         }
4516
4517         if (flags & PRINTER_ENUM_NAME) {
4518                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4519                                                      msg_ctx, servername, info,
4520                                                      count);
4521         }
4522
4523         if (flags & PRINTER_ENUM_NETWORK) {
4524                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4525                                                         msg_ctx, servername, info,
4526                                                         count);
4527         }
4528
4529         return WERR_OK; /* NT4sp5 does that */
4530 }
4531
4532 /********************************************************************
4533  * handle enumeration of printers at level 2
4534  ********************************************************************/
4535
4536 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4537                                   const struct auth_session_info *session_info,
4538                                   struct messaging_context *msg_ctx,
4539                                   uint32_t flags,
4540                                   const char *servername,
4541                                   union spoolss_PrinterInfo **info,
4542                                   uint32_t *count)
4543 {
4544         if (flags & PRINTER_ENUM_LOCAL) {
4545
4546                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4547                                                 servername,
4548                                                 info, count);
4549         }
4550
4551         if (flags & PRINTER_ENUM_NAME) {
4552                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4553                         return WERR_INVALID_NAME;
4554                 }
4555
4556                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4557                                                 servername,
4558                                                 info, count);
4559         }
4560
4561         if (flags & PRINTER_ENUM_REMOTE) {
4562                 return WERR_UNKNOWN_LEVEL;
4563         }
4564
4565         return WERR_OK;
4566 }
4567
4568 /********************************************************************
4569  * handle enumeration of printers at level 4
4570  ********************************************************************/
4571
4572 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4573                                   const struct auth_session_info *session_info,
4574                                   struct messaging_context *msg_ctx,
4575                                   uint32_t flags,
4576                                   const char *servername,
4577                                   union spoolss_PrinterInfo **info,
4578                                   uint32_t *count)
4579 {
4580         DEBUG(4,("enum_all_printers_info_4\n"));
4581
4582         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4583                                             servername, 4, flags, info, count);
4584 }
4585
4586
4587 /********************************************************************
4588  * handle enumeration of printers at level 5
4589  ********************************************************************/
4590
4591 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4592                                   const struct auth_session_info *session_info,
4593                                   struct messaging_context *msg_ctx,
4594                                   uint32_t flags,
4595                                   const char *servername,
4596                                   union spoolss_PrinterInfo **info,
4597                                   uint32_t *count)
4598 {
4599         DEBUG(4,("enum_all_printers_info_5\n"));
4600
4601         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4602                                             servername, 5, flags, info, count);
4603 }
4604
4605 /****************************************************************
4606  _spoolss_EnumPrinters
4607 ****************************************************************/
4608
4609 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4610                              struct spoolss_EnumPrinters *r)
4611 {
4612         const struct auth_session_info *session_info = get_session_info_system();
4613         WERROR result;
4614
4615         /* that's an [in out] buffer */
4616
4617         if (!r->in.buffer && (r->in.offered != 0)) {
4618                 return WERR_INVALID_PARAM;
4619         }
4620
4621         DEBUG(4,("_spoolss_EnumPrinters\n"));
4622
4623         *r->out.needed = 0;
4624         *r->out.count = 0;
4625         *r->out.info = NULL;
4626
4627         /*
4628          * Level 1:
4629          *          flags==PRINTER_ENUM_NAME
4630          *           if name=="" then enumerates all printers
4631          *           if name!="" then enumerate the printer
4632          *          flags==PRINTER_ENUM_REMOTE
4633          *          name is NULL, enumerate printers
4634          * Level 2: name!="" enumerates printers, name can't be NULL
4635          * Level 3: doesn't exist
4636          * Level 4: does a local registry lookup
4637          * Level 5: same as Level 2
4638          */
4639
4640         if (r->in.server && r->in.server[0] == '\0') {
4641                 r->in.server = NULL;
4642         }
4643
4644         switch (r->in.level) {
4645         case 0:
4646                 result = enumprinters_level0(p->mem_ctx, session_info,
4647                                              p->msg_ctx, r->in.flags,
4648                                              r->in.server,
4649                                              r->out.info, r->out.count);
4650                 break;
4651         case 1:
4652                 result = enumprinters_level1(p->mem_ctx, session_info,
4653                                              p->msg_ctx, r->in.flags,
4654                                              r->in.server,
4655                                              r->out.info, r->out.count);
4656                 break;
4657         case 2:
4658                 result = enumprinters_level2(p->mem_ctx, session_info,
4659                                              p->msg_ctx, r->in.flags,
4660                                              r->in.server,
4661                                              r->out.info, r->out.count);
4662                 break;
4663         case 4:
4664                 result = enumprinters_level4(p->mem_ctx, session_info,
4665                                              p->msg_ctx, r->in.flags,
4666                                              r->in.server,
4667                                              r->out.info, r->out.count);
4668                 break;
4669         case 5:
4670                 result = enumprinters_level5(p->mem_ctx, session_info,
4671                                              p->msg_ctx, r->in.flags,
4672                                              r->in.server,
4673                                              r->out.info, r->out.count);
4674                 break;
4675         default:
4676                 return WERR_UNKNOWN_LEVEL;
4677         }
4678
4679         if (!W_ERROR_IS_OK(result)) {
4680                 return result;
4681         }
4682
4683         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4684                                                      spoolss_EnumPrinters,
4685                                                      *r->out.info, r->in.level,
4686                                                      *r->out.count);
4687         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4688         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4689
4690         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4691 }
4692
4693 /****************************************************************
4694  _spoolss_GetPrinter
4695 ****************************************************************/
4696
4697 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4698                            struct spoolss_GetPrinter *r)
4699 {
4700         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4701         struct spoolss_PrinterInfo2 *info2 = NULL;
4702         WERROR result = WERR_OK;
4703         int snum;
4704
4705         /* that's an [in out] buffer */
4706
4707         if (!r->in.buffer && (r->in.offered != 0)) {
4708                 return WERR_INVALID_PARAM;
4709         }
4710
4711         *r->out.needed = 0;
4712
4713         if (Printer == NULL) {
4714                 return WERR_BADFID;
4715         }
4716
4717         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4718                 return WERR_BADFID;
4719         }
4720
4721         result = winreg_get_printer_internal(p->mem_ctx,
4722                                     get_session_info_system(),
4723                                     p->msg_ctx,
4724                                     lp_const_servicename(snum),
4725                                     &info2);
4726         if (!W_ERROR_IS_OK(result)) {
4727                 goto out;
4728         }
4729
4730         switch (r->in.level) {
4731         case 0:
4732                 result = construct_printer_info0(p->mem_ctx,
4733                                                  get_session_info_system(),
4734                                                  p->msg_ctx,
4735                                                  info2,
4736                                                  Printer->servername,
4737                                                  &r->out.info->info0,
4738                                                  snum);
4739                 break;
4740         case 1:
4741                 result = construct_printer_info1(p->mem_ctx, info2,
4742                                                  PRINTER_ENUM_ICON8,
4743                                                  Printer->servername,
4744                                                  &r->out.info->info1, snum);
4745                 break;
4746         case 2:
4747                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4748                                                  Printer->servername,
4749                                                  &r->out.info->info2, snum);
4750                 break;
4751         case 3:
4752                 result = construct_printer_info3(p->mem_ctx, info2,
4753                                                  Printer->servername,
4754                                                  &r->out.info->info3, snum);
4755                 break;
4756         case 4:
4757                 result = construct_printer_info4(p->mem_ctx, info2,
4758                                                  Printer->servername,
4759                                                  &r->out.info->info4, snum);
4760                 break;
4761         case 5:
4762                 result = construct_printer_info5(p->mem_ctx, info2,
4763                                                  Printer->servername,
4764                                                  &r->out.info->info5, snum);
4765                 break;
4766         case 6:
4767                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4768                                                  Printer->servername,
4769                                                  &r->out.info->info6, snum);
4770                 break;
4771         case 7:
4772                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4773                                                  Printer->servername,
4774                                                  &r->out.info->info7, snum);
4775                 break;
4776         case 8:
4777                 result = construct_printer_info8(p->mem_ctx, info2,
4778                                                  Printer->servername,
4779                                                  &r->out.info->info8, snum);
4780                 break;
4781         default:
4782                 result = WERR_UNKNOWN_LEVEL;
4783                 break;
4784         }
4785         TALLOC_FREE(info2);
4786
4787  out:
4788         if (!W_ERROR_IS_OK(result)) {
4789                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4790                           r->in.level, win_errstr(result)));
4791                 TALLOC_FREE(r->out.info);
4792                 return result;
4793         }
4794
4795         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4796                                                r->out.info, r->in.level);
4797         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4798
4799         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4800 }
4801
4802 /********************************************************************
4803  ********************************************************************/
4804
4805 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4806         do { \
4807                 if (in && strlen(in)) { \
4808                         out = talloc_strdup(mem_ctx, in); \
4809                 } else { \
4810                         out = talloc_strdup(mem_ctx, ""); \
4811                 } \
4812                 W_ERROR_HAVE_NO_MEMORY(out); \
4813         } while (0);
4814
4815 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4816         do { \
4817                 if (in && strlen(in)) { \
4818                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4819                 } else { \
4820                         out = talloc_strdup(mem_ctx, ""); \
4821                 } \
4822                 W_ERROR_HAVE_NO_MEMORY(out); \
4823         } while (0);
4824
4825 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4826                                                   const char **string_array,
4827                                                   const char ***presult,
4828                                                   const char *cservername,
4829                                                   const char *arch,
4830                                                   int version)
4831 {
4832         int i, num_strings = 0;
4833         const char **array = NULL;
4834
4835         if (string_array == NULL) {
4836                 return WERR_INVALID_PARAMETER;
4837         }
4838
4839         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4840                 const char *str = NULL;
4841
4842                 if (cservername == NULL || arch == NULL) {
4843                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4844                 } else {
4845                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4846                 }
4847
4848                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4849                         TALLOC_FREE(array);
4850                         return WERR_NOMEM;
4851                 }
4852         }
4853
4854         if (i > 0) {
4855                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4856                              &array, &num_strings);
4857         }
4858
4859         if (presult) {
4860                 *presult = array;
4861         }
4862
4863         return WERR_OK;
4864 }
4865
4866 /********************************************************************
4867  * fill a spoolss_DriverInfo1 struct
4868  ********************************************************************/
4869
4870 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4871                                         struct spoolss_DriverInfo1 *r,
4872                                         const struct spoolss_DriverInfo8 *driver,
4873                                         const char *servername)
4874 {
4875         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4876         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4877
4878         return WERR_OK;
4879 }
4880
4881 /********************************************************************
4882  * fill a spoolss_DriverInfo2 struct
4883  ********************************************************************/
4884
4885 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4886                                         struct spoolss_DriverInfo2 *r,
4887                                         const struct spoolss_DriverInfo8 *driver,
4888                                         const char *servername)
4889
4890 {
4891         const char *cservername = canon_servername(servername);
4892
4893         r->version              = driver->version;
4894
4895         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4896         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4897         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4898         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4899
4900         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4901                                driver->architecture,
4902                                driver->version,
4903                                driver->driver_path,
4904                                r->driver_path);
4905
4906         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4907                                driver->architecture,
4908                                driver->version,
4909                                driver->data_file,
4910                                r->data_file);
4911
4912         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4913                                driver->architecture,
4914                                driver->version,
4915                                driver->config_file,
4916                                r->config_file);
4917
4918         return WERR_OK;
4919 }
4920
4921 /********************************************************************
4922  * fill a spoolss_DriverInfo3 struct
4923  ********************************************************************/
4924
4925 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4926                                         struct spoolss_DriverInfo3 *r,
4927                                         const struct spoolss_DriverInfo8 *driver,
4928                                         const char *servername)
4929 {
4930         const char *cservername = canon_servername(servername);
4931
4932         r->version              = driver->version;
4933
4934         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4935         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4936         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4937         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4938
4939         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4940                                driver->architecture,
4941                                driver->version,
4942                                driver->driver_path,
4943                                r->driver_path);
4944
4945         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4946                                driver->architecture,
4947                                driver->version,
4948                                driver->data_file,
4949                                r->data_file);
4950
4951         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4952                                driver->architecture,
4953                                driver->version,
4954                                driver->config_file,
4955                                r->config_file);
4956
4957         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4958                                driver->architecture,
4959                                driver->version,
4960                                driver->help_file,
4961                                r->help_file);
4962
4963         FILL_DRIVER_STRING(mem_ctx,
4964                            driver->monitor_name,
4965                            r->monitor_name);
4966
4967         FILL_DRIVER_STRING(mem_ctx,
4968                            driver->default_datatype,
4969                            r->default_datatype);
4970
4971         return string_array_from_driver_info(mem_ctx,
4972                                              driver->dependent_files,
4973                                              &r->dependent_files,
4974                                              cservername,
4975                                              driver->architecture,
4976                                              driver->version);
4977 }
4978
4979 /********************************************************************
4980  * fill a spoolss_DriverInfo4 struct
4981  ********************************************************************/
4982
4983 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4984                                         struct spoolss_DriverInfo4 *r,
4985                                         const struct spoolss_DriverInfo8 *driver,
4986                                         const char *servername)
4987 {
4988         const char *cservername = canon_servername(servername);
4989         WERROR result;
4990
4991         r->version              = driver->version;
4992
4993         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4994         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4995         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4996         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4997
4998         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4999                                driver->architecture,
5000                                driver->version,
5001                                driver->driver_path,
5002                                r->driver_path);
5003
5004         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5005                                driver->architecture,
5006                                driver->version,
5007                                driver->data_file,
5008                                r->data_file);
5009
5010         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5011                                driver->architecture,
5012                                driver->version,
5013                                driver->config_file,
5014                                r->config_file);
5015
5016         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5017                                driver->architecture,
5018                                driver->version,
5019                                driver->help_file,
5020                                r->help_file);
5021
5022         result = string_array_from_driver_info(mem_ctx,
5023                                                driver->dependent_files,
5024                                                &r->dependent_files,
5025                                                cservername,
5026                                                driver->architecture,
5027                                                driver->version);
5028         if (!W_ERROR_IS_OK(result)) {
5029                 return result;
5030         }
5031
5032         FILL_DRIVER_STRING(mem_ctx,
5033                            driver->monitor_name,
5034                            r->monitor_name);
5035
5036         FILL_DRIVER_STRING(mem_ctx,
5037                            driver->default_datatype,
5038                            r->default_datatype);
5039
5040
5041         result = string_array_from_driver_info(mem_ctx,
5042                                                driver->previous_names,
5043                                                &r->previous_names,
5044                                                NULL, NULL, 0);
5045
5046         return result;
5047 }
5048
5049 /********************************************************************
5050  * fill a spoolss_DriverInfo5 struct
5051  ********************************************************************/
5052
5053 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5054                                         struct spoolss_DriverInfo5 *r,
5055                                         const struct spoolss_DriverInfo8 *driver,
5056                                         const char *servername)
5057 {
5058         const char *cservername = canon_servername(servername);
5059
5060         r->version              = driver->version;
5061
5062         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5063         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5064         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5065         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5066
5067         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5068                                driver->architecture,
5069                                driver->version,
5070                                driver->driver_path,
5071                                r->driver_path);
5072
5073         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5074                                driver->architecture,
5075                                driver->version,
5076                                driver->data_file,
5077                                r->data_file);
5078
5079         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5080                                driver->architecture,
5081                                driver->version,
5082                                driver->config_file,
5083                                r->config_file);
5084
5085         r->driver_attributes    = 0;
5086         r->config_version       = 0;
5087         r->driver_version       = 0;
5088
5089         return WERR_OK;
5090 }
5091 /********************************************************************
5092  * fill a spoolss_DriverInfo6 struct
5093  ********************************************************************/
5094
5095 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5096                                         struct spoolss_DriverInfo6 *r,
5097                                         const struct spoolss_DriverInfo8 *driver,
5098                                         const char *servername)
5099 {
5100         const char *cservername = canon_servername(servername);
5101         WERROR result;
5102
5103         r->version              = driver->version;
5104
5105         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5106         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5107         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5108         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5109
5110         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5111                                driver->architecture,
5112                                driver->version,
5113                                driver->driver_path,
5114                                r->driver_path);
5115
5116         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5117                                driver->architecture,
5118                                driver->version,
5119                                driver->data_file,
5120                                r->data_file);
5121
5122         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5123                                driver->architecture,
5124                                driver->version,
5125                                driver->config_file,
5126                                r->config_file);
5127
5128         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5129                                driver->architecture,
5130                                driver->version,
5131                                driver->help_file,
5132                                r->help_file);
5133
5134         FILL_DRIVER_STRING(mem_ctx,
5135                            driver->monitor_name,
5136                            r->monitor_name);
5137
5138         FILL_DRIVER_STRING(mem_ctx,
5139                            driver->default_datatype,
5140                            r->default_datatype);
5141
5142         result = string_array_from_driver_info(mem_ctx,
5143                                                driver->dependent_files,
5144                                                &r->dependent_files,
5145                                                cservername,
5146                                                driver->architecture,
5147                                                driver->version);
5148         if (!W_ERROR_IS_OK(result)) {
5149                 return result;
5150         }
5151
5152         result = string_array_from_driver_info(mem_ctx,
5153                                                driver->previous_names,
5154                                                &r->previous_names,
5155                                                NULL, NULL, 0);
5156         if (!W_ERROR_IS_OK(result)) {
5157                 return result;
5158         }
5159
5160         r->driver_date          = driver->driver_date;
5161         r->driver_version       = driver->driver_version;
5162
5163         FILL_DRIVER_STRING(mem_ctx,
5164                            driver->manufacturer_name,
5165                            r->manufacturer_name);
5166         FILL_DRIVER_STRING(mem_ctx,
5167                            driver->manufacturer_url,
5168                            r->manufacturer_url);
5169         FILL_DRIVER_STRING(mem_ctx,
5170                            driver->hardware_id,
5171                            r->hardware_id);
5172         FILL_DRIVER_STRING(mem_ctx,
5173                            driver->provider,
5174                            r->provider);
5175
5176         return WERR_OK;
5177 }
5178
5179 /********************************************************************
5180  * fill a spoolss_DriverInfo8 struct
5181  ********************************************************************/
5182
5183 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5184                                         struct spoolss_DriverInfo8 *r,
5185                                         const struct spoolss_DriverInfo8 *driver,
5186                                         const char *servername)
5187 {
5188         const char *cservername = canon_servername(servername);
5189         WERROR result;
5190
5191         r->version              = driver->version;
5192
5193         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5194         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5195         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5196         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5197
5198         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5199                                driver->architecture,
5200                                driver->version,
5201                                driver->driver_path,
5202                                r->driver_path);
5203
5204         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5205                                driver->architecture,
5206                                driver->version,
5207                                driver->data_file,
5208                                r->data_file);
5209
5210         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5211                                driver->architecture,
5212                                driver->version,
5213                                driver->config_file,
5214                                r->config_file);
5215
5216         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5217                                driver->architecture,
5218                                driver->version,
5219                                driver->help_file,
5220                                r->help_file);
5221
5222         FILL_DRIVER_STRING(mem_ctx,
5223                            driver->monitor_name,
5224                            r->monitor_name);
5225
5226         FILL_DRIVER_STRING(mem_ctx,
5227                            driver->default_datatype,
5228                            r->default_datatype);
5229
5230         result = string_array_from_driver_info(mem_ctx,
5231                                                driver->dependent_files,
5232                                                &r->dependent_files,
5233                                                cservername,
5234                                                driver->architecture,
5235                                                driver->version);
5236         if (!W_ERROR_IS_OK(result)) {
5237                 return result;
5238         }
5239
5240         result = string_array_from_driver_info(mem_ctx,
5241                                                driver->previous_names,
5242                                                &r->previous_names,
5243                                                NULL, NULL, 0);
5244         if (!W_ERROR_IS_OK(result)) {
5245                 return result;
5246         }
5247
5248         r->driver_date          = driver->driver_date;
5249         r->driver_version       = driver->driver_version;
5250
5251         FILL_DRIVER_STRING(mem_ctx,
5252                            driver->manufacturer_name,
5253                            r->manufacturer_name);
5254         FILL_DRIVER_STRING(mem_ctx,
5255                            driver->manufacturer_url,
5256                            r->manufacturer_url);
5257         FILL_DRIVER_STRING(mem_ctx,
5258                            driver->hardware_id,
5259                            r->hardware_id);
5260         FILL_DRIVER_STRING(mem_ctx,
5261                            driver->provider,
5262                            r->provider);
5263
5264         FILL_DRIVER_STRING(mem_ctx,
5265                            driver->print_processor,
5266                            r->print_processor);
5267         FILL_DRIVER_STRING(mem_ctx,
5268                            driver->vendor_setup,
5269                            r->vendor_setup);
5270
5271         result = string_array_from_driver_info(mem_ctx,
5272                                                driver->color_profiles,
5273                                                &r->color_profiles,
5274                                                NULL, NULL, 0);
5275         if (!W_ERROR_IS_OK(result)) {
5276                 return result;
5277         }
5278
5279         FILL_DRIVER_STRING(mem_ctx,
5280                            driver->inf_path,
5281                            r->inf_path);
5282
5283         r->printer_driver_attributes    = driver->printer_driver_attributes;
5284
5285         result = string_array_from_driver_info(mem_ctx,
5286                                                driver->core_driver_dependencies,
5287                                                &r->core_driver_dependencies,
5288                                                NULL, NULL, 0);
5289         if (!W_ERROR_IS_OK(result)) {
5290                 return result;
5291         }
5292
5293         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5294         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5295
5296         return WERR_OK;
5297 }
5298
5299 #if 0 /* disabled until marshalling issues are resolved - gd */
5300 /********************************************************************
5301  ********************************************************************/
5302
5303 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5304                                           struct spoolss_DriverFileInfo *r,
5305                                           const char *cservername,
5306                                           const char *file_name,
5307                                           enum spoolss_DriverFileType file_type,
5308                                           uint32_t file_version)
5309 {
5310         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5311                                           cservername, file_name);
5312         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5313         r->file_type    = file_type;
5314         r->file_version = file_version;
5315
5316         return WERR_OK;
5317 }
5318
5319 /********************************************************************
5320  ********************************************************************/
5321
5322 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5323                                                  const struct spoolss_DriverInfo8 *driver,
5324                                                  const char *cservername,
5325                                                  struct spoolss_DriverFileInfo **info_p,
5326                                                  uint32_t *count_p)
5327 {
5328         struct spoolss_DriverFileInfo *info = NULL;
5329         uint32_t count = 0;
5330         WERROR result;
5331         uint32_t i;
5332
5333         *info_p = NULL;
5334         *count_p = 0;
5335
5336         if (strlen(driver->driver_path)) {
5337                 info = talloc_realloc(mem_ctx, info,
5338                                             struct spoolss_DriverFileInfo,
5339                                             count + 1);
5340                 W_ERROR_HAVE_NO_MEMORY(info);
5341                 result = fill_spoolss_DriverFileInfo(info,
5342                                                      &info[count],
5343                                                      cservername,
5344                                                      driver->driver_path,
5345                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5346                                                      0);
5347                 W_ERROR_NOT_OK_RETURN(result);
5348                 count++;
5349         }
5350
5351         if (strlen(driver->config_file)) {
5352                 info = talloc_realloc(mem_ctx, info,
5353                                             struct spoolss_DriverFileInfo,
5354                                             count + 1);
5355                 W_ERROR_HAVE_NO_MEMORY(info);
5356                 result = fill_spoolss_DriverFileInfo(info,
5357                                                      &info[count],
5358                                                      cservername,
5359                                                      driver->config_file,
5360                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5361                                                      0);
5362                 W_ERROR_NOT_OK_RETURN(result);
5363                 count++;
5364         }
5365
5366         if (strlen(driver->data_file)) {
5367                 info = talloc_realloc(mem_ctx, info,
5368                                             struct spoolss_DriverFileInfo,
5369                                             count + 1);
5370                 W_ERROR_HAVE_NO_MEMORY(info);
5371                 result = fill_spoolss_DriverFileInfo(info,
5372                                                      &info[count],
5373                                                      cservername,
5374                                                      driver->data_file,
5375                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5376                                                      0);
5377                 W_ERROR_NOT_OK_RETURN(result);
5378                 count++;
5379         }
5380
5381         if (strlen(driver->help_file)) {
5382                 info = talloc_realloc(mem_ctx, info,
5383                                             struct spoolss_DriverFileInfo,
5384                                             count + 1);
5385                 W_ERROR_HAVE_NO_MEMORY(info);
5386                 result = fill_spoolss_DriverFileInfo(info,
5387                                                      &info[count],
5388                                                      cservername,
5389                                                      driver->help_file,
5390                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5391                                                      0);
5392                 W_ERROR_NOT_OK_RETURN(result);
5393                 count++;
5394         }
5395
5396         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5397                 info = talloc_realloc(mem_ctx, info,
5398                                             struct spoolss_DriverFileInfo,
5399                                             count + 1);
5400                 W_ERROR_HAVE_NO_MEMORY(info);
5401                 result = fill_spoolss_DriverFileInfo(info,
5402                                                      &info[count],
5403                                                      cservername,
5404                                                      driver->dependent_files[i],
5405                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5406                                                      0);
5407                 W_ERROR_NOT_OK_RETURN(result);
5408                 count++;
5409         }
5410
5411         *info_p = info;
5412         *count_p = count;
5413
5414         return WERR_OK;
5415 }
5416
5417 /********************************************************************
5418  * fill a spoolss_DriverInfo101 struct
5419  ********************************************************************/
5420
5421 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5422                                           struct spoolss_DriverInfo101 *r,
5423                                           const struct spoolss_DriverInfo8 *driver,
5424                                           const char *servername)
5425 {
5426         const char *cservername = canon_servername(servername);
5427         WERROR result;
5428
5429         r->version              = driver->version;
5430
5431         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5432         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5433         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5434         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5435
5436         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5437                                                     cservername,
5438                                                     &r->file_info,
5439                                                     &r->file_count);
5440         if (!W_ERROR_IS_OK(result)) {
5441                 return result;
5442         }
5443
5444         FILL_DRIVER_STRING(mem_ctx,
5445                            driver->monitor_name,
5446                            r->monitor_name);
5447
5448         FILL_DRIVER_STRING(mem_ctx,
5449                            driver->default_datatype,
5450                            r->default_datatype);
5451
5452         result = string_array_from_driver_info(mem_ctx,
5453                                                driver->previous_names,
5454                                                &r->previous_names,
5455                                                NULL, NULL, 0);
5456         if (!W_ERROR_IS_OK(result)) {
5457                 return result;
5458         }
5459
5460         r->driver_date          = driver->driver_date;
5461         r->driver_version       = driver->driver_version;
5462
5463         FILL_DRIVER_STRING(mem_ctx,
5464                            driver->manufacturer_name,
5465                            r->manufacturer_name);
5466         FILL_DRIVER_STRING(mem_ctx,
5467                            driver->manufacturer_url,
5468                            r->manufacturer_url);
5469         FILL_DRIVER_STRING(mem_ctx,
5470                            driver->hardware_id,
5471                            r->hardware_id);
5472         FILL_DRIVER_STRING(mem_ctx,
5473                            driver->provider,
5474                            r->provider);
5475
5476         return WERR_OK;
5477 }
5478 #endif
5479 /********************************************************************
5480  ********************************************************************/
5481
5482 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5483                                                   const struct auth_session_info *session_info,
5484                                                   struct messaging_context *msg_ctx,
5485                                                   uint32_t level,
5486                                                   union spoolss_DriverInfo *r,
5487                                                   int snum,
5488                                                   const char *servername,
5489                                                   const char *architecture,
5490                                                   uint32_t version)
5491 {
5492         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5493         struct spoolss_DriverInfo8 *driver;
5494         WERROR result;
5495         struct dcerpc_binding_handle *b;
5496         TALLOC_CTX *tmp_ctx = NULL;
5497
5498         if (level == 101) {
5499                 return WERR_UNKNOWN_LEVEL;
5500         }
5501
5502         tmp_ctx = talloc_new(mem_ctx);
5503         if (!tmp_ctx) {
5504                 return WERR_NOMEM;
5505         }
5506
5507         result = winreg_printer_binding_handle(tmp_ctx,
5508                                                session_info,
5509                                                msg_ctx,
5510                                                &b);
5511         if (!W_ERROR_IS_OK(result)) {
5512                 goto done;
5513         }
5514
5515         result = winreg_get_printer(tmp_ctx, b,
5516                                     lp_const_servicename(snum),
5517                                     &pinfo2);
5518
5519         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5520                 win_errstr(result)));
5521
5522         if (!W_ERROR_IS_OK(result)) {
5523                 result = WERR_INVALID_PRINTER_NAME;
5524                 goto done;
5525         }
5526
5527         result = winreg_get_driver(tmp_ctx, b,
5528                                    architecture,
5529                                    pinfo2->drivername, version, &driver);
5530
5531         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5532                 win_errstr(result)));
5533
5534         if (!W_ERROR_IS_OK(result)) {
5535                 /*
5536                  * Is this a W2k client ?
5537                  */
5538
5539                 if (version < 3) {
5540                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5541                         goto done;
5542                 }
5543
5544                 /* Yes - try again with a WinNT driver. */
5545                 version = 2;
5546                 result = winreg_get_driver(tmp_ctx, b,
5547                                            architecture,
5548                                            pinfo2->drivername,
5549                                            version, &driver);
5550                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5551                         win_errstr(result)));
5552                 if (!W_ERROR_IS_OK(result)) {
5553                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5554                         goto done;
5555                 }
5556         }
5557
5558         /* these are allocated on mem_ctx and not tmp_ctx because they are
5559          * the 'return value' and need to utlive this call */
5560         switch (level) {
5561         case 1:
5562                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5563                 break;
5564         case 2:
5565                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5566                 break;
5567         case 3:
5568                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5569                 break;
5570         case 4:
5571                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5572                 break;
5573         case 5:
5574                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5575                 break;
5576         case 6:
5577                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5578                 break;
5579         case 8:
5580                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5581                 break;
5582 #if 0 /* disabled until marshalling issues are resolved - gd */
5583         case 101:
5584                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5585                 break;
5586 #endif
5587         default:
5588                 result = WERR_UNKNOWN_LEVEL;
5589                 break;
5590         }
5591
5592 done:
5593         talloc_free(tmp_ctx);
5594         return result;
5595 }
5596
5597 /****************************************************************
5598  _spoolss_GetPrinterDriver2
5599 ****************************************************************/
5600
5601 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5602                                   struct spoolss_GetPrinterDriver2 *r)
5603 {
5604         struct printer_handle *printer;
5605         WERROR result;
5606
5607         int snum;
5608
5609         /* that's an [in out] buffer */
5610
5611         if (!r->in.buffer && (r->in.offered != 0)) {
5612                 return WERR_INVALID_PARAM;
5613         }
5614
5615         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5616
5617         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5618                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5619                 return WERR_INVALID_PRINTER_NAME;
5620         }
5621
5622         *r->out.needed = 0;
5623         *r->out.server_major_version = 0;
5624         *r->out.server_minor_version = 0;
5625
5626         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5627                 return WERR_BADFID;
5628         }
5629
5630         result = construct_printer_driver_info_level(p->mem_ctx,
5631                                                      get_session_info_system(),
5632                                                      p->msg_ctx,
5633                                                      r->in.level, r->out.info,
5634                                                      snum, printer->servername,
5635                                                      r->in.architecture,
5636                                                      r->in.client_major_version);
5637         if (!W_ERROR_IS_OK(result)) {
5638                 TALLOC_FREE(r->out.info);
5639                 return result;
5640         }
5641
5642         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5643                                                r->out.info, r->in.level);
5644         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5645
5646         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5647 }
5648
5649
5650 /****************************************************************
5651  _spoolss_StartPagePrinter
5652 ****************************************************************/
5653
5654 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5655                                  struct spoolss_StartPagePrinter *r)
5656 {
5657         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5658
5659         if (!Printer) {
5660                 DEBUG(3,("_spoolss_StartPagePrinter: "
5661                         "Error in startpageprinter printer handle\n"));
5662                 return WERR_BADFID;
5663         }
5664
5665         Printer->page_started = true;
5666         return WERR_OK;
5667 }
5668
5669 /****************************************************************
5670  _spoolss_EndPagePrinter
5671 ****************************************************************/
5672
5673 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5674                                struct spoolss_EndPagePrinter *r)
5675 {
5676         int snum;
5677
5678         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5679
5680         if (!Printer) {
5681                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5682                         OUR_HANDLE(r->in.handle)));
5683                 return WERR_BADFID;
5684         }
5685
5686         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5687                 return WERR_BADFID;
5688
5689         Printer->page_started = false;
5690         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5691
5692         return WERR_OK;
5693 }
5694
5695 /****************************************************************
5696  _spoolss_StartDocPrinter
5697 ****************************************************************/
5698
5699 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5700                                 struct spoolss_StartDocPrinter *r)
5701 {
5702         struct spoolss_DocumentInfo1 *info_1;
5703         int snum;
5704         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5705         WERROR werr;
5706         char *rhost;
5707         int rc;
5708
5709         if (!Printer) {
5710                 DEBUG(2,("_spoolss_StartDocPrinter: "
5711                         "Invalid handle (%s:%u:%u)\n",
5712                         OUR_HANDLE(r->in.handle)));
5713                 return WERR_BADFID;
5714         }
5715
5716         if (Printer->jobid) {
5717                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5718                           "StartDocPrinter called twice! "
5719                           "(existing jobid = %d)\n", Printer->jobid));
5720                 return WERR_INVALID_HANDLE;
5721         }
5722
5723         if (r->in.level != 1) {
5724                 return WERR_UNKNOWN_LEVEL;
5725         }
5726
5727         info_1 = r->in.info.info1;
5728
5729         /*
5730          * a nice thing with NT is it doesn't listen to what you tell it.
5731          * when asked to send _only_ RAW datas, it tries to send datas
5732          * in EMF format.
5733          *
5734          * So I add checks like in NT Server ...
5735          */
5736
5737         if (info_1->datatype) {
5738                 if (strcmp(info_1->datatype, "RAW") != 0) {
5739                         *r->out.job_id = 0;
5740                         return WERR_INVALID_DATATYPE;
5741                 }
5742         }
5743
5744         /* get the share number of the printer */
5745         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5746                 return WERR_BADFID;
5747         }
5748
5749         rc = get_remote_hostname(p->remote_address,
5750                                  &rhost,
5751                                  p->mem_ctx);
5752         if (rc < 0) {
5753                 return WERR_NOMEM;
5754         }
5755         if (strequal(rhost,"UNKNOWN")) {
5756                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5757                                                          p->mem_ctx);
5758                 if (rhost == NULL) {
5759                         return WERR_NOMEM;
5760                 }
5761         }
5762
5763         werr = print_job_start(p->session_info,
5764                                p->msg_ctx,
5765                                rhost,
5766                                snum,
5767                                info_1->document_name,
5768                                info_1->output_file,
5769                                Printer->devmode,
5770                                &Printer->jobid);
5771
5772         /* An error occured in print_job_start() so return an appropriate
5773            NT error code. */
5774
5775         if (!W_ERROR_IS_OK(werr)) {
5776                 return werr;
5777         }
5778
5779         Printer->document_started = true;
5780         *r->out.job_id = Printer->jobid;
5781
5782         return WERR_OK;
5783 }
5784
5785 /****************************************************************
5786  _spoolss_EndDocPrinter
5787 ****************************************************************/
5788
5789 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5790                               struct spoolss_EndDocPrinter *r)
5791 {
5792         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5793         NTSTATUS status;
5794         int snum;
5795
5796         if (!Printer) {
5797                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5798                         OUR_HANDLE(r->in.handle)));
5799                 return WERR_BADFID;
5800         }
5801
5802         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5803                 return WERR_BADFID;
5804         }
5805
5806         Printer->document_started = false;
5807         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5808         if (!NT_STATUS_IS_OK(status)) {
5809                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5810                           "print_job_end failed [%s]\n",
5811                           nt_errstr(status)));
5812         }
5813
5814         Printer->jobid = 0;
5815         return ntstatus_to_werror(status);
5816 }
5817
5818 /****************************************************************
5819  _spoolss_WritePrinter
5820 ****************************************************************/
5821
5822 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5823                              struct spoolss_WritePrinter *r)
5824 {
5825         ssize_t buffer_written;
5826         int snum;
5827         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5828
5829         if (!Printer) {
5830                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5831                         OUR_HANDLE(r->in.handle)));
5832                 *r->out.num_written = r->in._data_size;
5833                 return WERR_BADFID;
5834         }
5835
5836         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5837                 return WERR_BADFID;
5838
5839         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5840         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5841                                                    snum, Printer->jobid,
5842                                                    (const char *)r->in.data.data,
5843                                                    (size_t)r->in._data_size);
5844         if (buffer_written == (ssize_t)-1) {
5845                 *r->out.num_written = 0;
5846                 if (errno == ENOSPC)
5847                         return WERR_NO_SPOOL_SPACE;
5848                 else
5849                         return WERR_ACCESS_DENIED;
5850         }
5851
5852         *r->out.num_written = r->in._data_size;
5853
5854         return WERR_OK;
5855 }
5856
5857 /********************************************************************
5858  * api_spoolss_getprinter
5859  * called from the spoolss dispatcher
5860  *
5861  ********************************************************************/
5862
5863 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5864                               struct pipes_struct *p)
5865 {
5866         const struct auth_session_info *session_info = p->session_info;
5867         int snum;
5868         WERROR errcode = WERR_BADFUNC;
5869         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5870
5871         if (!Printer) {
5872                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5873                         OUR_HANDLE(handle)));
5874                 return WERR_BADFID;
5875         }
5876
5877         if (!get_printer_snum(p, handle, &snum, NULL))
5878                 return WERR_BADFID;
5879
5880         switch (command) {
5881         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5882                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5883                 break;
5884         case SPOOLSS_PRINTER_CONTROL_RESUME:
5885         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5886                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5887                 break;
5888         case SPOOLSS_PRINTER_CONTROL_PURGE:
5889                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5890                 break;
5891         default:
5892                 return WERR_UNKNOWN_LEVEL;
5893         }
5894
5895         return errcode;
5896 }
5897
5898
5899 /****************************************************************
5900  _spoolss_AbortPrinter
5901  * From MSDN: "Deletes printer's spool file if printer is configured
5902  * for spooling"
5903 ****************************************************************/
5904
5905 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5906                              struct spoolss_AbortPrinter *r)
5907 {
5908         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5909         int             snum;
5910         WERROR          errcode = WERR_OK;
5911
5912         if (!Printer) {
5913                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5914                         OUR_HANDLE(r->in.handle)));
5915                 return WERR_BADFID;
5916         }
5917
5918         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5919                 return WERR_BADFID;
5920
5921         if (!Printer->document_started) {
5922                 return WERR_SPL_NO_STARTDOC;
5923         }
5924
5925         errcode = print_job_delete(p->session_info,
5926                                    p->msg_ctx,
5927                                    snum,
5928                                    Printer->jobid);
5929
5930         return errcode;
5931 }
5932
5933 /********************************************************************
5934  * called by spoolss_api_setprinter
5935  * when updating a printer description
5936  ********************************************************************/
5937
5938 static WERROR update_printer_sec(struct policy_handle *handle,
5939                                  struct pipes_struct *p,
5940                                  struct sec_desc_buf *secdesc_ctr)
5941 {
5942         struct spoolss_security_descriptor *new_secdesc = NULL;
5943         struct spoolss_security_descriptor *old_secdesc = NULL;
5944         const char *printer;
5945         WERROR result;
5946         int snum;
5947         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5948         struct dcerpc_binding_handle *b;
5949         TALLOC_CTX *tmp_ctx = NULL;
5950
5951         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5952                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5953                          OUR_HANDLE(handle)));
5954
5955                 result = WERR_BADFID;
5956                 goto done;
5957         }
5958
5959         if (secdesc_ctr == NULL) {
5960                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5961                 result = WERR_INVALID_PARAM;
5962                 goto done;
5963         }
5964         printer = lp_const_servicename(snum);
5965
5966         /* Check the user has permissions to change the security
5967            descriptor.  By experimentation with two NT machines, the user
5968            requires Full Access to the printer to change security
5969            information. */
5970
5971         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5972                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5973                 result = WERR_ACCESS_DENIED;
5974                 goto done;
5975         }
5976
5977         tmp_ctx = talloc_new(p->mem_ctx);
5978         if (!tmp_ctx) {
5979                 return WERR_NOMEM;
5980         }
5981
5982         result = winreg_printer_binding_handle(tmp_ctx,
5983                                                get_session_info_system(),
5984                                                p->msg_ctx,
5985                                                &b);
5986         if (!W_ERROR_IS_OK(result)) {
5987                 goto done;
5988         }
5989
5990         /* NT seems to like setting the security descriptor even though
5991            nothing may have actually changed. */
5992         result = winreg_get_printer_secdesc(tmp_ctx, b,
5993                                             printer,
5994                                             &old_secdesc);
5995         if (!W_ERROR_IS_OK(result)) {
5996                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
5997                 result = WERR_BADFID;
5998                 goto done;
5999         }
6000
6001         if (DEBUGLEVEL >= 10) {
6002                 struct security_acl *the_acl;
6003                 int i;
6004
6005                 the_acl = old_secdesc->dacl;
6006                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6007                            printer, the_acl->num_aces));
6008
6009                 for (i = 0; i < the_acl->num_aces; i++) {
6010                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6011                                            &the_acl->aces[i].trustee),
6012                                   the_acl->aces[i].access_mask));
6013                 }
6014
6015                 the_acl = secdesc_ctr->sd->dacl;
6016
6017                 if (the_acl) {
6018                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6019                                    printer, the_acl->num_aces));
6020
6021                         for (i = 0; i < the_acl->num_aces; i++) {
6022                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6023                                                    &the_acl->aces[i].trustee),
6024                                            the_acl->aces[i].access_mask));
6025                         }
6026                 } else {
6027                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6028                 }
6029         }
6030
6031         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6032         if (new_secdesc == NULL) {
6033                 result = WERR_NOMEM;
6034                 goto done;
6035         }
6036
6037         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6038                 result = WERR_OK;
6039                 goto done;
6040         }
6041
6042         result = winreg_set_printer_secdesc(tmp_ctx, b,
6043                                             printer,
6044                                             new_secdesc);
6045
6046 done:
6047         talloc_free(tmp_ctx);
6048         return result;
6049 }
6050
6051 /********************************************************************
6052  Canonicalize printer info from a client
6053  ********************************************************************/
6054
6055 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6056                              struct spoolss_SetPrinterInfo2 *info2,
6057                              int snum)
6058 {
6059         fstring printername;
6060         const char *p;
6061
6062         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6063                 "portname=%s drivername=%s comment=%s location=%s\n",
6064                 info2->servername, info2->printername, info2->sharename,
6065                 info2->portname, info2->drivername, info2->comment,
6066                 info2->location));
6067
6068         /* we force some elements to "correct" values */
6069         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6070         if (info2->servername == NULL) {
6071                 return false;
6072         }
6073         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6074         if (info2->sharename == NULL) {
6075                 return false;
6076         }
6077
6078         /* check to see if we allow printername != sharename */
6079         if (lp_force_printername(snum)) {
6080                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6081                                         lp_netbios_name(), info2->sharename);
6082         } else {
6083                 /* make sure printername is in \\server\printername format */
6084                 fstrcpy(printername, info2->printername);
6085                 p = printername;
6086                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6087                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6088                                 p++;
6089                 }
6090
6091                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6092                                         lp_netbios_name(), p);
6093         }
6094         if (info2->printername == NULL) {
6095                 return false;
6096         }
6097
6098         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6099         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6100
6101         return true;
6102 }
6103
6104 /****************************************************************************
6105 ****************************************************************************/
6106
6107 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6108 {
6109         char *cmd = lp_addport_cmd(talloc_tos());
6110         char *command = NULL;
6111         int ret;
6112         bool is_print_op = false;
6113
6114         if ( !*cmd ) {
6115                 return WERR_ACCESS_DENIED;
6116         }
6117
6118         command = talloc_asprintf(ctx,
6119                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6120         if (!command) {
6121                 return WERR_NOMEM;
6122         }
6123
6124         if ( token )
6125                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6126
6127         DEBUG(10,("Running [%s]\n", command));
6128
6129         /********* BEGIN SePrintOperatorPrivilege **********/
6130
6131         if ( is_print_op )
6132                 become_root();
6133
6134         ret = smbrun(command, NULL);
6135
6136         if ( is_print_op )
6137                 unbecome_root();
6138
6139         /********* END SePrintOperatorPrivilege **********/
6140
6141         DEBUGADD(10,("returned [%d]\n", ret));
6142
6143         TALLOC_FREE(command);
6144
6145         if ( ret != 0 ) {
6146                 return WERR_ACCESS_DENIED;
6147         }
6148
6149         return WERR_OK;
6150 }
6151
6152 /****************************************************************************
6153 ****************************************************************************/
6154
6155 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6156                                    int snum)
6157 {
6158         /*
6159          * As we do not know if we are embedded in the file server process
6160          * or not, we have to pretend that all shares are in use.
6161          */
6162         return true;
6163 }
6164
6165 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6166                              struct spoolss_SetPrinterInfo2 *info2,
6167                              const char *remote_machine,
6168                              struct messaging_context *msg_ctx)
6169 {
6170         char *cmd = lp_addprinter_cmd(talloc_tos());
6171         char **qlines;
6172         char *command = NULL;
6173         int numlines;
6174         int ret;
6175         int fd;
6176         bool is_print_op = false;
6177
6178         if (!remote_machine) {
6179                 return false;
6180         }
6181
6182         command = talloc_asprintf(ctx,
6183                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6184                         cmd, info2->printername, info2->sharename,
6185                         info2->portname, info2->drivername,
6186                         info2->location, info2->comment, remote_machine);
6187         if (!command) {
6188                 return false;
6189         }
6190
6191         if ( token )
6192                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6193
6194         DEBUG(10,("Running [%s]\n", command));
6195
6196         /********* BEGIN SePrintOperatorPrivilege **********/
6197
6198         if ( is_print_op )
6199                 become_root();
6200
6201         if ( (ret = smbrun(command, &fd)) == 0 ) {
6202                 /* Tell everyone we updated smb.conf. */
6203                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6204         }
6205
6206         if ( is_print_op )
6207                 unbecome_root();
6208
6209         /********* END SePrintOperatorPrivilege **********/
6210
6211         DEBUGADD(10,("returned [%d]\n", ret));
6212
6213         TALLOC_FREE(command);
6214
6215         if ( ret != 0 ) {
6216                 if (fd != -1)
6217                         close(fd);
6218                 return false;
6219         }
6220
6221         /* reload our services immediately */
6222         become_root();
6223         reload_services(NULL, spoolss_conn_snum_used, false);
6224         unbecome_root();
6225
6226         numlines = 0;
6227         /* Get lines and convert them back to dos-codepage */
6228         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6229         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6230         close(fd);
6231
6232         /* Set the portname to what the script says the portname should be. */
6233         /* but don't require anything to be return from the script exit a good error code */
6234
6235         if (numlines) {
6236                 /* Set the portname to what the script says the portname should be. */
6237                 info2->portname = talloc_strdup(ctx, qlines[0]);
6238                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6239         }
6240
6241         TALLOC_FREE(qlines);
6242         return true;
6243 }
6244
6245 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6246                                const struct auth_session_info *session_info,
6247                                struct messaging_context *msg_ctx,
6248                                int snum,
6249                                struct spoolss_SetPrinterInfo2 *printer,
6250                                struct spoolss_PrinterInfo2 *old_printer)
6251 {
6252         bool force_update = (old_printer == NULL);
6253         const char *dnsdomname;
6254         const char *longname;
6255         const char *uncname;
6256         const char *spooling;
6257         DATA_BLOB buffer;
6258         WERROR result = WERR_OK;
6259         struct dcerpc_binding_handle *b;
6260         TALLOC_CTX *tmp_ctx;
6261         bool ok;
6262
6263         tmp_ctx = talloc_new(mem_ctx);
6264         if (!tmp_ctx) {
6265                 return WERR_NOMEM;
6266         }
6267
6268         result = winreg_printer_binding_handle(tmp_ctx,
6269                                                session_info,
6270                                                msg_ctx,
6271                                                &b);
6272         if (!W_ERROR_IS_OK(result)) {
6273                 goto done;
6274         }
6275
6276         if (printer->drivername != NULL &&
6277             (force_update ||
6278              !strequal(printer->drivername, old_printer->drivername))) {
6279                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6280                 if (!ok) {
6281                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6282                         result = WERR_INVALID_DATA;
6283                         goto done;
6284                 }
6285                 result = winreg_set_printer_dataex(tmp_ctx, b,
6286                                           printer->sharename,
6287                                           SPOOL_DSSPOOLER_KEY,
6288                                           SPOOL_REG_DRIVERNAME,
6289                                           REG_SZ,
6290                                           buffer.data,
6291                                           buffer.length);
6292                 if (!W_ERROR_IS_OK(result)) {
6293                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6294                         goto done;
6295                 }
6296
6297                 if (!force_update) {
6298                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6299                                 printer->drivername));
6300
6301                         notify_printer_driver(server_event_context(), msg_ctx,
6302                                               snum, printer->drivername ?
6303                                               printer->drivername : "");
6304                 }
6305         }
6306
6307         if (printer->comment != NULL &&
6308             (force_update ||
6309              !strequal(printer->comment, old_printer->comment))) {
6310                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6311                 if (!ok) {
6312                         DEBUG(0, ("comment data corrupted\n"));
6313                         result = WERR_INVALID_DATA;
6314                         goto done;
6315                 }
6316                 result = winreg_set_printer_dataex(tmp_ctx, b,
6317                                           printer->sharename,
6318                                           SPOOL_DSSPOOLER_KEY,
6319                                           SPOOL_REG_DESCRIPTION,
6320                                           REG_SZ,
6321                                           buffer.data,
6322                                           buffer.length);
6323                 if (!W_ERROR_IS_OK(result)) {
6324                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6325                         goto done;
6326                 }
6327
6328                 if (!force_update) {
6329                         notify_printer_comment(server_event_context(), msg_ctx,
6330                                                snum, printer->comment ?
6331                                                printer->comment : "");
6332                 }
6333         }
6334
6335         if (printer->sharename != NULL &&
6336             (force_update ||
6337              !strequal(printer->sharename, old_printer->sharename))) {
6338                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6339                 if (!ok) {
6340                         DEBUG(0, ("sharename data corrupted\n"));
6341                         result = WERR_INVALID_DATA;
6342                         goto done;
6343                 }
6344                 result = winreg_set_printer_dataex(tmp_ctx, b,
6345                                           printer->sharename,
6346                                           SPOOL_DSSPOOLER_KEY,
6347                                           SPOOL_REG_PRINTSHARENAME,
6348                                           REG_SZ,
6349                                           buffer.data,
6350                                           buffer.length);
6351                 if (!W_ERROR_IS_OK(result)) {
6352                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6353                         goto done;
6354                 }
6355
6356                 if (!force_update) {
6357                         notify_printer_sharename(server_event_context(),
6358                                                  msg_ctx,
6359                                                  snum, printer->sharename ?
6360                                                  printer->sharename : "");
6361                 }
6362         }
6363
6364         if (printer->printername != NULL &&
6365             (force_update ||
6366              !strequal(printer->printername, old_printer->printername))) {
6367                 const char *p;
6368
6369                 p = strrchr(printer->printername, '\\' );
6370                 if (p != NULL) {
6371                         p++;
6372                 } else {
6373                         p = printer->printername;
6374                 }
6375
6376                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6377                 if (!ok) {
6378                         DEBUG(0, ("printername data corrupted\n"));
6379                         result = WERR_INVALID_DATA;
6380                         goto done;
6381                 }
6382                 result = winreg_set_printer_dataex(tmp_ctx, b,
6383                                           printer->sharename,
6384                                           SPOOL_DSSPOOLER_KEY,
6385                                           SPOOL_REG_PRINTERNAME,
6386                                           REG_SZ,
6387                                           buffer.data,
6388                                           buffer.length);
6389                 if (!W_ERROR_IS_OK(result)) {
6390                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6391                         goto done;
6392                 }
6393
6394                 if (!force_update) {
6395                         notify_printer_printername(server_event_context(),
6396                                                    msg_ctx, snum, p ? p : "");
6397                 }
6398         }
6399
6400         if (printer->portname != NULL &&
6401             (force_update ||
6402              !strequal(printer->portname, old_printer->portname))) {
6403                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6404                 if (!ok) {
6405                         DEBUG(0, ("portname data corrupted\n"));
6406                         result = WERR_INVALID_DATA;
6407                         goto done;
6408                 }
6409                 result = winreg_set_printer_dataex(tmp_ctx, b,
6410                                           printer->sharename,
6411                                           SPOOL_DSSPOOLER_KEY,
6412                                           SPOOL_REG_PORTNAME,
6413                                           REG_SZ,
6414                                           buffer.data,
6415                                           buffer.length);
6416                 if (!W_ERROR_IS_OK(result)) {
6417                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6418                         goto done;
6419                 }
6420
6421                 if (!force_update) {
6422                         notify_printer_port(server_event_context(),
6423                                             msg_ctx, snum, printer->portname ?
6424                                             printer->portname : "");
6425                 }
6426         }
6427
6428         if (printer->location != NULL &&
6429             (force_update ||
6430              !strequal(printer->location, old_printer->location))) {
6431                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6432                 if (!ok) {
6433                         DEBUG(0, ("location data corrupted\n"));
6434                         result = WERR_INVALID_DATA;
6435                         goto done;
6436                 }
6437                 result = winreg_set_printer_dataex(tmp_ctx, b,
6438                                           printer->sharename,
6439                                           SPOOL_DSSPOOLER_KEY,
6440                                           SPOOL_REG_LOCATION,
6441                                           REG_SZ,
6442                                           buffer.data,
6443                                           buffer.length);
6444                 if (!W_ERROR_IS_OK(result)) {
6445                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6446                         goto done;
6447                 }
6448
6449                 if (!force_update) {
6450                         notify_printer_location(server_event_context(),
6451                                                 msg_ctx, snum,
6452                                                 printer->location ?
6453                                                 printer->location : "");
6454                 }
6455         }
6456
6457         if (printer->sepfile != NULL &&
6458             (force_update ||
6459              !strequal(printer->sepfile, old_printer->sepfile))) {
6460                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6461                 if (!ok) {
6462                         DEBUG(0, ("sepfile data corrupted\n"));
6463                         result = WERR_INVALID_DATA;
6464                         goto done;
6465                 }
6466                 result = winreg_set_printer_dataex(tmp_ctx, b,
6467                                           printer->sharename,
6468                                           SPOOL_DSSPOOLER_KEY,
6469                                           SPOOL_REG_PRINTSEPARATORFILE,
6470                                           REG_SZ,
6471                                           buffer.data,
6472                                           buffer.length);
6473                 if (!W_ERROR_IS_OK(result)) {
6474                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6475                         goto done;
6476                 }
6477
6478                 if (!force_update) {
6479                         notify_printer_sepfile(server_event_context(),
6480                                                msg_ctx, snum,
6481                                                printer->sepfile ?
6482                                                printer->sepfile : "");
6483                 }
6484         }
6485
6486         if (printer->starttime != 0 &&
6487             (force_update ||
6488              printer->starttime != old_printer->starttime)) {
6489                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6490                 SIVAL(buffer.data, 0, printer->starttime);
6491                 result = winreg_set_printer_dataex(tmp_ctx, b,
6492                                           printer->sharename,
6493                                           SPOOL_DSSPOOLER_KEY,
6494                                           SPOOL_REG_PRINTSTARTTIME,
6495                                           REG_DWORD,
6496                                           buffer.data,
6497                                           buffer.length);
6498                 if (!W_ERROR_IS_OK(result)) {
6499                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6500                         goto done;
6501                 }
6502         }
6503
6504         if (printer->untiltime != 0 &&
6505             (force_update ||
6506              printer->untiltime != old_printer->untiltime)) {
6507                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6508                 SIVAL(buffer.data, 0, printer->untiltime);
6509                 result = winreg_set_printer_dataex(tmp_ctx, b,
6510                                           printer->sharename,
6511                                           SPOOL_DSSPOOLER_KEY,
6512                                           SPOOL_REG_PRINTENDTIME,
6513                                           REG_DWORD,
6514                                           buffer.data,
6515                                           buffer.length);
6516                 if (!W_ERROR_IS_OK(result)) {
6517                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6518                         goto done;
6519                 }
6520         }
6521
6522         if (force_update || printer->priority != old_printer->priority) {
6523                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6524                 SIVAL(buffer.data, 0, printer->priority);
6525                 result = winreg_set_printer_dataex(tmp_ctx, b,
6526                                           printer->sharename,
6527                                           SPOOL_DSSPOOLER_KEY,
6528                                           SPOOL_REG_PRIORITY,
6529                                           REG_DWORD,
6530                                           buffer.data,
6531                                           buffer.length);
6532                 if (!W_ERROR_IS_OK(result)) {
6533                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6534                         goto done;
6535                 }
6536         }
6537
6538         if (force_update || printer->attributes != old_printer->attributes) {
6539                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6540                 SIVAL(buffer.data, 0, (printer->attributes &
6541                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6542                 result = winreg_set_printer_dataex(tmp_ctx, b,
6543                                           printer->sharename,
6544                                           SPOOL_DSSPOOLER_KEY,
6545                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6546                                           REG_DWORD,
6547                                           buffer.data,
6548                                           buffer.length);
6549                 if (!W_ERROR_IS_OK(result)) {
6550                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6551                         goto done;
6552                 }
6553
6554                 switch (printer->attributes & 0x3) {
6555                         case 0:
6556                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6557                                 break;
6558                         case 1:
6559                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6560                                 break;
6561                         case 2:
6562                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6563                                 break;
6564                         default:
6565                                 spooling = "unknown";
6566                 }
6567                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6568                 if (!ok) {
6569                         DEBUG(0, ("printSpooling data corrupted\n"));
6570                         result = WERR_INVALID_DATA;
6571                         goto done;
6572                 }
6573                 winreg_set_printer_dataex(tmp_ctx, b,
6574                                           printer->sharename,
6575                                           SPOOL_DSSPOOLER_KEY,
6576                                           SPOOL_REG_PRINTSPOOLING,
6577                                           REG_SZ,
6578                                           buffer.data,
6579                                           buffer.length);
6580         }
6581
6582         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6583         if (!ok) {
6584                 DEBUG(0, ("shortServerName data corrupted\n"));
6585                 result = WERR_INVALID_DATA;
6586                 goto done;
6587         }
6588         result = winreg_set_printer_dataex(tmp_ctx, b,
6589                                   printer->sharename,
6590                                   SPOOL_DSSPOOLER_KEY,
6591                                   SPOOL_REG_SHORTSERVERNAME,
6592                                   REG_SZ,
6593                                   buffer.data,
6594                                   buffer.length);
6595         if (!W_ERROR_IS_OK(result)) {
6596                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6597                 goto done;
6598         }
6599
6600         dnsdomname = get_mydnsfullname();
6601         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6602                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6603         } else {
6604                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6605         }
6606         if (longname == NULL) {
6607                 result = WERR_NOMEM;
6608                 goto done;
6609         }
6610
6611         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6612         if (!ok) {
6613                 DEBUG(0, ("longname data corrupted\n"));
6614                 result = WERR_INVALID_DATA;
6615                 goto done;
6616         }
6617         result = winreg_set_printer_dataex(tmp_ctx, b,
6618                                            printer->sharename,
6619                                            SPOOL_DSSPOOLER_KEY,
6620                                            SPOOL_REG_SERVERNAME,
6621                                            REG_SZ,
6622                                            buffer.data,
6623                                            buffer.length);
6624         if (!W_ERROR_IS_OK(result)) {
6625                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6626                 goto done;
6627         }
6628
6629         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6630                                   lp_netbios_name(), printer->sharename);
6631         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6632         if (!ok) {
6633                 DEBUG(0, ("uncName data corrupted\n"));
6634                 result = WERR_INVALID_DATA;
6635                 goto done;
6636         }
6637         result = winreg_set_printer_dataex(tmp_ctx, b,
6638                                   printer->sharename,
6639                                   SPOOL_DSSPOOLER_KEY,
6640                                   SPOOL_REG_UNCNAME,
6641                                   REG_SZ,
6642                                   buffer.data,
6643                                   buffer.length);
6644         if (!W_ERROR_IS_OK(result)) {
6645                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6646                 goto done;
6647         }
6648
6649 done:
6650         talloc_free(tmp_ctx);
6651         return result;
6652 }
6653
6654 /********************************************************************
6655  * Called by spoolss_api_setprinter
6656  * when updating a printer description.
6657  ********************************************************************/
6658
6659 static WERROR update_printer(struct pipes_struct *p,
6660                              struct policy_handle *handle,
6661                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6662                              struct spoolss_DeviceMode *devmode)
6663 {
6664         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6665         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6666         struct spoolss_PrinterInfo2 *old_printer;
6667         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6668         int snum;
6669         WERROR result = WERR_OK;
6670         TALLOC_CTX *tmp_ctx;
6671         struct dcerpc_binding_handle *b;
6672
6673         DEBUG(8,("update_printer\n"));
6674
6675         tmp_ctx = talloc_new(p->mem_ctx);
6676         if (tmp_ctx == NULL) {
6677                 return WERR_NOMEM;
6678         }
6679
6680         if (!Printer) {
6681                 result = WERR_BADFID;
6682                 goto done;
6683         }
6684
6685         if (!get_printer_snum(p, handle, &snum, NULL)) {
6686                 result = WERR_BADFID;
6687                 goto done;
6688         }
6689
6690         result = winreg_printer_binding_handle(tmp_ctx,
6691                                                get_session_info_system(),
6692                                                p->msg_ctx,
6693                                                &b);
6694         if (!W_ERROR_IS_OK(result)) {
6695                 goto done;
6696         }
6697
6698         result = winreg_get_printer(tmp_ctx, b,
6699                                     lp_const_servicename(snum),
6700                                     &old_printer);
6701         if (!W_ERROR_IS_OK(result)) {
6702                 result = WERR_BADFID;
6703                 goto done;
6704         }
6705
6706         /* Do sanity check on the requested changes for Samba */
6707         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6708                 result = WERR_INVALID_PARAM;
6709                 goto done;
6710         }
6711
6712         /* FIXME!!! If the driver has changed we really should verify that
6713            it is installed before doing much else   --jerry */
6714
6715         /* Check calling user has permission to update printer description */
6716         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6717                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6718                 result = WERR_ACCESS_DENIED;
6719                 goto done;
6720         }
6721
6722         /* Call addprinter hook */
6723         /* Check changes to see if this is really needed */
6724
6725         if (*lp_addprinter_cmd(talloc_tos()) &&
6726                         (!strequal(printer->drivername, old_printer->drivername) ||
6727                          !strequal(printer->comment, old_printer->comment) ||
6728                          !strequal(printer->portname, old_printer->portname) ||
6729                          !strequal(printer->location, old_printer->location)) )
6730         {
6731                 char *raddr;
6732
6733                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6734                                                          p->mem_ctx);
6735                 if (raddr == NULL) {
6736                         return WERR_NOMEM;
6737                 }
6738
6739                 /* add_printer_hook() will call reload_services() */
6740                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6741                                       printer, raddr,
6742                                       p->msg_ctx)) {
6743                         result = WERR_ACCESS_DENIED;
6744                         goto done;
6745                 }
6746         }
6747
6748         result = update_dsspooler(tmp_ctx,
6749                                   get_session_info_system(),
6750                                   p->msg_ctx,
6751                                   snum,
6752                                   printer,
6753                                   old_printer);
6754         if (!W_ERROR_IS_OK(result)) {
6755                 goto done;
6756         }
6757
6758         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6759
6760         if (devmode == NULL) {
6761                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6762         }
6763         result = winreg_update_printer(tmp_ctx, b,
6764                                        printer->sharename,
6765                                        printer_mask,
6766                                        printer,
6767                                        devmode,
6768                                        NULL);
6769
6770 done:
6771         talloc_free(tmp_ctx);
6772
6773         return result;
6774 }
6775
6776 /****************************************************************************
6777 ****************************************************************************/
6778 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6779                                            struct policy_handle *handle,
6780                                            struct spoolss_SetPrinterInfo7 *info7)
6781 {
6782 #ifdef HAVE_ADS
6783         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6784         WERROR result;
6785         int snum;
6786         struct printer_handle *Printer;
6787
6788         if ( lp_security() != SEC_ADS ) {
6789                 return WERR_UNKNOWN_LEVEL;
6790         }
6791
6792         Printer = find_printer_index_by_hnd(p, handle);
6793
6794         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6795
6796         if (!Printer)
6797                 return WERR_BADFID;
6798
6799         if (!get_printer_snum(p, handle, &snum, NULL))
6800                 return WERR_BADFID;
6801
6802         result = winreg_get_printer_internal(p->mem_ctx,
6803                                     get_session_info_system(),
6804                                     p->msg_ctx,
6805                                     lp_servicename(talloc_tos(), snum),
6806                                     &pinfo2);
6807         if (!W_ERROR_IS_OK(result)) {
6808                 return WERR_BADFID;
6809         }
6810
6811         nt_printer_publish(pinfo2,
6812                            get_session_info_system(),
6813                            p->msg_ctx,
6814                            pinfo2,
6815                            info7->action);
6816
6817         TALLOC_FREE(pinfo2);
6818         return WERR_OK;
6819 #else
6820         return WERR_UNKNOWN_LEVEL;
6821 #endif
6822 }
6823
6824 /********************************************************************
6825  ********************************************************************/
6826
6827 static WERROR update_printer_devmode(struct pipes_struct *p,
6828                                      struct policy_handle *handle,
6829                                      struct spoolss_DeviceMode *devmode)
6830 {
6831         int snum;
6832         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6833         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6834
6835         DEBUG(8,("update_printer_devmode\n"));
6836
6837         if (!Printer) {
6838                 return WERR_BADFID;
6839         }
6840
6841         if (!get_printer_snum(p, handle, &snum, NULL)) {
6842                 return WERR_BADFID;
6843         }
6844
6845         /* Check calling user has permission to update printer description */
6846         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6847                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6848                 return WERR_ACCESS_DENIED;
6849         }
6850
6851         return winreg_update_printer_internal(p->mem_ctx,
6852                                      get_session_info_system(),
6853                                      p->msg_ctx,
6854                                      lp_const_servicename(snum),
6855                                      info2_mask,
6856                                      NULL,
6857                                      devmode,
6858                                      NULL);
6859 }
6860
6861
6862 /****************************************************************
6863  _spoolss_SetPrinter
6864 ****************************************************************/
6865
6866 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6867                            struct spoolss_SetPrinter *r)
6868 {
6869         WERROR result;
6870
6871         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6872
6873         if (!Printer) {
6874                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6875                         OUR_HANDLE(r->in.handle)));
6876                 return WERR_BADFID;
6877         }
6878
6879         /* check the level */
6880         switch (r->in.info_ctr->level) {
6881                 case 0:
6882                         return control_printer(r->in.handle, r->in.command, p);
6883                 case 2:
6884                         result = update_printer(p, r->in.handle,
6885                                                 r->in.info_ctr,
6886                                                 r->in.devmode_ctr->devmode);
6887                         if (!W_ERROR_IS_OK(result))
6888                                 return result;
6889                         if (r->in.secdesc_ctr->sd)
6890                                 result = update_printer_sec(r->in.handle, p,
6891                                                             r->in.secdesc_ctr);
6892                         return result;
6893                 case 3:
6894                         return update_printer_sec(r->in.handle, p,
6895                                                   r->in.secdesc_ctr);
6896                 case 7:
6897                         return publish_or_unpublish_printer(p, r->in.handle,
6898                                                             r->in.info_ctr->info.info7);
6899                 case 8:
6900                         return update_printer_devmode(p, r->in.handle,
6901                                                       r->in.devmode_ctr->devmode);
6902                 default:
6903                         return WERR_UNKNOWN_LEVEL;
6904         }
6905 }
6906
6907 /****************************************************************
6908  _spoolss_FindClosePrinterNotify
6909 ****************************************************************/
6910
6911 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6912                                        struct spoolss_FindClosePrinterNotify *r)
6913 {
6914         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6915
6916         if (!Printer) {
6917                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6918                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6919                 return WERR_BADFID;
6920         }
6921
6922         if (Printer->notify.cli_chan != NULL &&
6923             Printer->notify.cli_chan->active_connections > 0) {
6924                 int snum = -1;
6925
6926                 if (Printer->printer_type == SPLHND_PRINTER) {
6927                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6928                                 return WERR_BADFID;
6929                         }
6930                 }
6931
6932                 srv_spoolss_replycloseprinter(snum, Printer);
6933         }
6934
6935         Printer->notify.flags=0;
6936         Printer->notify.options=0;
6937         Printer->notify.localmachine[0]='\0';
6938         Printer->notify.printerlocal=0;
6939         TALLOC_FREE(Printer->notify.option);
6940
6941         return WERR_OK;
6942 }
6943
6944 /****************************************************************
6945  _spoolss_AddJob
6946 ****************************************************************/
6947
6948 WERROR _spoolss_AddJob(struct pipes_struct *p,
6949                        struct spoolss_AddJob *r)
6950 {
6951         if (!r->in.buffer && (r->in.offered != 0)) {
6952                 return WERR_INVALID_PARAM;
6953         }
6954
6955         /* this is what a NT server returns for AddJob. AddJob must fail on
6956          * non-local printers */
6957
6958         if (r->in.level != 1) {
6959                 return WERR_UNKNOWN_LEVEL;
6960         }
6961
6962         return WERR_INVALID_PARAM;
6963 }
6964
6965 /****************************************************************************
6966 fill_job_info1
6967 ****************************************************************************/
6968
6969 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6970                              struct spoolss_JobInfo1 *r,
6971                              const print_queue_struct *queue,
6972                              int position, int snum,
6973                              struct spoolss_PrinterInfo2 *pinfo2)
6974 {
6975         struct tm *t;
6976
6977         t = gmtime(&queue->time);
6978
6979         r->job_id               = queue->sysjob;
6980
6981         r->printer_name         = lp_servicename(mem_ctx, snum);
6982         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6983         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6984         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6985         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6986         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6987         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6988         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6989         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6990         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6991         r->text_status          = talloc_strdup(mem_ctx, "");
6992         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6993
6994         r->status               = nt_printj_status(queue->status);
6995         r->priority             = queue->priority;
6996         r->position             = position;
6997         r->total_pages          = queue->page_count;
6998         r->pages_printed        = 0; /* ??? */
6999
7000         init_systemtime(&r->submitted, t);
7001
7002         return WERR_OK;
7003 }
7004
7005 /****************************************************************************
7006 fill_job_info2
7007 ****************************************************************************/
7008
7009 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7010                              struct spoolss_JobInfo2 *r,
7011                              const print_queue_struct *queue,
7012                              int position, int snum,
7013                              struct spoolss_PrinterInfo2 *pinfo2,
7014                              struct spoolss_DeviceMode *devmode)
7015 {
7016         struct tm *t;
7017
7018         t = gmtime(&queue->time);
7019
7020         r->job_id               = queue->sysjob;
7021
7022         r->printer_name         = lp_servicename(mem_ctx, snum);
7023         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7024         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7025         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7026         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7027         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7028         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7029         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7030         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7031         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7032         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7033         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7034         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7035         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7036         r->parameters           = talloc_strdup(mem_ctx, "");
7037         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7038         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7039         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7040
7041         r->devmode              = devmode;
7042
7043         r->text_status          = talloc_strdup(mem_ctx, "");
7044         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7045
7046         r->secdesc              = NULL;
7047
7048         r->status               = nt_printj_status(queue->status);
7049         r->priority             = queue->priority;
7050         r->position             = position;
7051         r->start_time           = 0;
7052         r->until_time           = 0;
7053         r->total_pages          = queue->page_count;
7054         r->size                 = queue->size;
7055         init_systemtime(&r->submitted, t);
7056         r->time                 = 0;
7057         r->pages_printed        = 0; /* ??? */
7058
7059         return WERR_OK;
7060 }
7061
7062 /****************************************************************************
7063 fill_job_info3
7064 ****************************************************************************/
7065
7066 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7067                              struct spoolss_JobInfo3 *r,
7068                              const print_queue_struct *queue,
7069                              const print_queue_struct *next_queue,
7070                              int position, int snum,
7071                              struct spoolss_PrinterInfo2 *pinfo2)
7072 {
7073         r->job_id               = queue->sysjob;
7074         r->next_job_id          = 0;
7075         if (next_queue) {
7076                 r->next_job_id  = next_queue->sysjob;
7077         }
7078         r->reserved             = 0;
7079
7080         return WERR_OK;
7081 }
7082
7083 /****************************************************************************
7084  Enumjobs at level 1.
7085 ****************************************************************************/
7086
7087 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7088                               const print_queue_struct *queue,
7089                               uint32_t num_queues, int snum,
7090                               struct spoolss_PrinterInfo2 *pinfo2,
7091                               union spoolss_JobInfo **info_p,
7092                               uint32_t *count)
7093 {
7094         union spoolss_JobInfo *info;
7095         int i;
7096         WERROR result = WERR_OK;
7097
7098         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7099         W_ERROR_HAVE_NO_MEMORY(info);
7100
7101         *count = num_queues;
7102
7103         for (i=0; i<*count; i++) {
7104                 result = fill_job_info1(info,
7105                                         &info[i].info1,
7106                                         &queue[i],
7107                                         i,
7108                                         snum,
7109                                         pinfo2);
7110                 if (!W_ERROR_IS_OK(result)) {
7111                         goto out;
7112                 }
7113         }
7114
7115  out:
7116         if (!W_ERROR_IS_OK(result)) {
7117                 TALLOC_FREE(info);
7118                 *count = 0;
7119                 return result;
7120         }
7121
7122         *info_p = info;
7123
7124         return WERR_OK;
7125 }
7126
7127 /****************************************************************************
7128  Enumjobs at level 2.
7129 ****************************************************************************/
7130
7131 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7132                               const print_queue_struct *queue,
7133                               uint32_t num_queues, int snum,
7134                               struct spoolss_PrinterInfo2 *pinfo2,
7135                               union spoolss_JobInfo **info_p,
7136                               uint32_t *count)
7137 {
7138         union spoolss_JobInfo *info;
7139         int i;
7140         WERROR result = WERR_OK;
7141
7142         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7143         W_ERROR_HAVE_NO_MEMORY(info);
7144
7145         *count = num_queues;
7146
7147         for (i=0; i<*count; i++) {
7148                 struct spoolss_DeviceMode *devmode;
7149
7150                 result = spoolss_create_default_devmode(info,
7151                                                         pinfo2->printername,
7152                                                         &devmode);
7153                 if (!W_ERROR_IS_OK(result)) {
7154                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7155                         goto out;
7156                 }
7157
7158                 result = fill_job_info2(info,
7159                                         &info[i].info2,
7160                                         &queue[i],
7161                                         i,
7162                                         snum,
7163                                         pinfo2,
7164                                         devmode);
7165                 if (!W_ERROR_IS_OK(result)) {
7166                         goto out;
7167                 }
7168         }
7169
7170  out:
7171         if (!W_ERROR_IS_OK(result)) {
7172                 TALLOC_FREE(info);
7173                 *count = 0;
7174                 return result;
7175         }
7176
7177         *info_p = info;
7178
7179         return WERR_OK;
7180 }
7181
7182 /****************************************************************************
7183  Enumjobs at level 3.
7184 ****************************************************************************/
7185
7186 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7187                               const print_queue_struct *queue,
7188                               uint32_t num_queues, int snum,
7189                               struct spoolss_PrinterInfo2 *pinfo2,
7190                               union spoolss_JobInfo **info_p,
7191                               uint32_t *count)
7192 {
7193         union spoolss_JobInfo *info;
7194         int i;
7195         WERROR result = WERR_OK;
7196
7197         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7198         W_ERROR_HAVE_NO_MEMORY(info);
7199
7200         *count = num_queues;
7201
7202         for (i=0; i<*count; i++) {
7203                 const print_queue_struct *next_queue = NULL;
7204
7205                 if (i+1 < *count) {
7206                         next_queue = &queue[i+1];
7207                 }
7208
7209                 result = fill_job_info3(info,
7210                                         &info[i].info3,
7211                                         &queue[i],
7212                                         next_queue,
7213                                         i,
7214                                         snum,
7215                                         pinfo2);
7216                 if (!W_ERROR_IS_OK(result)) {
7217                         goto out;
7218                 }
7219         }
7220
7221  out:
7222         if (!W_ERROR_IS_OK(result)) {
7223                 TALLOC_FREE(info);
7224                 *count = 0;
7225                 return result;
7226         }
7227
7228         *info_p = info;
7229
7230         return WERR_OK;
7231 }
7232
7233 /****************************************************************
7234  _spoolss_EnumJobs
7235 ****************************************************************/
7236
7237 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7238                          struct spoolss_EnumJobs *r)
7239 {
7240         WERROR result;
7241         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7242         int snum;
7243         print_status_struct prt_status;
7244         print_queue_struct *queue = NULL;
7245         uint32_t count;
7246
7247         /* that's an [in out] buffer */
7248
7249         if (!r->in.buffer && (r->in.offered != 0)) {
7250                 return WERR_INVALID_PARAM;
7251         }
7252
7253         DEBUG(4,("_spoolss_EnumJobs\n"));
7254
7255         *r->out.needed = 0;
7256         *r->out.count = 0;
7257         *r->out.info = NULL;
7258
7259         /* lookup the printer snum and tdb entry */
7260
7261         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7262                 return WERR_BADFID;
7263         }
7264
7265         result = winreg_get_printer_internal(p->mem_ctx,
7266                                     get_session_info_system(),
7267                                     p->msg_ctx,
7268                                     lp_const_servicename(snum),
7269                                     &pinfo2);
7270         if (!W_ERROR_IS_OK(result)) {
7271                 return result;
7272         }
7273
7274         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7275         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7276                 count, prt_status.status, prt_status.message));
7277
7278         if (count == 0) {
7279                 SAFE_FREE(queue);
7280                 TALLOC_FREE(pinfo2);
7281                 return WERR_OK;
7282         }
7283
7284         switch (r->in.level) {
7285         case 1:
7286                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7287                                          pinfo2, r->out.info, r->out.count);
7288                 break;
7289         case 2:
7290                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7291                                          pinfo2, r->out.info, r->out.count);
7292                 break;
7293         case 3:
7294                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7295                                          pinfo2, r->out.info, r->out.count);
7296                 break;
7297         default:
7298                 result = WERR_UNKNOWN_LEVEL;
7299                 break;
7300         }
7301
7302         SAFE_FREE(queue);
7303         TALLOC_FREE(pinfo2);
7304
7305         if (!W_ERROR_IS_OK(result)) {
7306                 return result;
7307         }
7308
7309         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7310                                                      spoolss_EnumJobs,
7311                                                      *r->out.info, r->in.level,
7312                                                      *r->out.count);
7313         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7314         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7315
7316         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7317 }
7318
7319 /****************************************************************
7320  _spoolss_ScheduleJob
7321 ****************************************************************/
7322
7323 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7324                             struct spoolss_ScheduleJob *r)
7325 {
7326         return WERR_OK;
7327 }
7328
7329 /****************************************************************
7330 ****************************************************************/
7331
7332 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7333                                struct messaging_context *msg_ctx,
7334                                const char *printer_name,
7335                                uint32_t job_id,
7336                                struct spoolss_SetJobInfo1 *r)
7337 {
7338         char *old_doc_name;
7339
7340         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7341                 return WERR_BADFID;
7342         }
7343
7344         if (strequal(old_doc_name, r->document_name)) {
7345                 return WERR_OK;
7346         }
7347
7348         if (!print_job_set_name(server_event_context(), msg_ctx,
7349                                 printer_name, job_id, r->document_name)) {
7350                 return WERR_BADFID;
7351         }
7352
7353         return WERR_OK;
7354 }
7355
7356 /****************************************************************
7357  _spoolss_SetJob
7358 ****************************************************************/
7359
7360 WERROR _spoolss_SetJob(struct pipes_struct *p,
7361                        struct spoolss_SetJob *r)
7362 {
7363         const struct auth_session_info *session_info = p->session_info;
7364         int snum;
7365         WERROR errcode = WERR_BADFUNC;
7366
7367         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7368                 return WERR_BADFID;
7369         }
7370
7371         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7372                 return WERR_INVALID_PRINTER_NAME;
7373         }
7374
7375         switch (r->in.command) {
7376         case SPOOLSS_JOB_CONTROL_CANCEL:
7377         case SPOOLSS_JOB_CONTROL_DELETE:
7378                 errcode = print_job_delete(session_info, p->msg_ctx,
7379                                            snum, r->in.job_id);
7380                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7381                         errcode = WERR_OK;
7382                 }
7383                 break;
7384         case SPOOLSS_JOB_CONTROL_PAUSE:
7385                 errcode = print_job_pause(session_info, p->msg_ctx,
7386                                           snum, r->in.job_id);
7387                 break;
7388         case SPOOLSS_JOB_CONTROL_RESTART:
7389         case SPOOLSS_JOB_CONTROL_RESUME:
7390                 errcode = print_job_resume(session_info, p->msg_ctx,
7391                                            snum, r->in.job_id);
7392                 break;
7393         case 0:
7394                 errcode = WERR_OK;
7395                 break;
7396         default:
7397                 return WERR_UNKNOWN_LEVEL;
7398         }
7399
7400         if (!W_ERROR_IS_OK(errcode)) {
7401                 return errcode;
7402         }
7403
7404         if (r->in.ctr == NULL) {
7405                 return errcode;
7406         }
7407
7408         switch (r->in.ctr->level) {
7409         case 1:
7410                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7411                                            lp_const_servicename(snum),
7412                                            r->in.job_id,
7413                                            r->in.ctr->info.info1);
7414                 break;
7415         case 2:
7416         case 3:
7417         case 4:
7418         default:
7419                 return WERR_UNKNOWN_LEVEL;
7420         }
7421
7422         return errcode;
7423 }
7424
7425 /****************************************************************************
7426  Enumerates all printer drivers by level and architecture.
7427 ****************************************************************************/
7428
7429 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7430                                                        const struct auth_session_info *session_info,
7431                                                        struct messaging_context *msg_ctx,
7432                                                        const char *servername,
7433                                                        const char *architecture,
7434                                                        uint32_t level,
7435                                                        union spoolss_DriverInfo **info_p,
7436                                                        uint32_t *count_p)
7437 {
7438         int i;
7439         uint32_t version;
7440         struct spoolss_DriverInfo8 *driver;
7441         union spoolss_DriverInfo *info = NULL;
7442         uint32_t count = 0;
7443         WERROR result = WERR_OK;
7444         uint32_t num_drivers;
7445         const char **drivers;
7446         struct dcerpc_binding_handle *b;
7447         TALLOC_CTX *tmp_ctx = NULL;
7448
7449         *count_p = 0;
7450         *info_p = NULL;
7451
7452         tmp_ctx = talloc_new(mem_ctx);
7453         if (!tmp_ctx) {
7454                 return WERR_NOMEM;
7455         }
7456
7457         result = winreg_printer_binding_handle(tmp_ctx,
7458                                                session_info,
7459                                                msg_ctx,
7460                                                &b);
7461         if (!W_ERROR_IS_OK(result)) {
7462                 goto out;
7463         }
7464
7465         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7466                 result = winreg_get_driver_list(tmp_ctx, b,
7467                                                 architecture, version,
7468                                                 &num_drivers, &drivers);
7469                 if (!W_ERROR_IS_OK(result)) {
7470                         goto out;
7471                 }
7472                 DEBUG(4, ("we have:[%d] drivers in environment"
7473                           " [%s] and version [%d]\n",
7474                           num_drivers, architecture, version));
7475
7476                 if (num_drivers != 0) {
7477                         info = talloc_realloc(tmp_ctx, info,
7478                                                     union spoolss_DriverInfo,
7479                                                     count + num_drivers);
7480                         if (!info) {
7481                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7482                                         "failed to enlarge driver info buffer!\n"));
7483                                 result = WERR_NOMEM;
7484                                 goto out;
7485                         }
7486                 }
7487
7488                 for (i = 0; i < num_drivers; i++) {
7489                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7490
7491                         result = winreg_get_driver(tmp_ctx, b,
7492                                                    architecture, drivers[i],
7493                                                    version, &driver);
7494                         if (!W_ERROR_IS_OK(result)) {
7495                                 goto out;
7496                         }
7497
7498                         switch (level) {
7499                         case 1:
7500                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7501                                                                    driver, servername);
7502                                 break;
7503                         case 2:
7504                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7505                                                                    driver, servername);
7506                                 break;
7507                         case 3:
7508                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7509                                                                    driver, servername);
7510                                 break;
7511                         case 4:
7512                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7513                                                                    driver, servername);
7514                                 break;
7515                         case 5:
7516                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7517                                                                    driver, servername);
7518                                 break;
7519                         case 6:
7520                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7521                                                                    driver, servername);
7522                                 break;
7523                         case 8:
7524                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7525                                                                    driver, servername);
7526                                 break;
7527                         default:
7528                                 result = WERR_UNKNOWN_LEVEL;
7529                                 break;
7530                         }
7531
7532                         TALLOC_FREE(driver);
7533
7534                         if (!W_ERROR_IS_OK(result)) {
7535                                 goto out;
7536                         }
7537                 }
7538
7539                 count += num_drivers;
7540                 TALLOC_FREE(drivers);
7541         }
7542
7543 out:
7544         if (W_ERROR_IS_OK(result)) {
7545                 *info_p = talloc_move(mem_ctx, &info);
7546                 *count_p = count;
7547         }
7548
7549         talloc_free(tmp_ctx);
7550         return result;
7551 }
7552
7553 /****************************************************************************
7554  Enumerates all printer drivers by level.
7555 ****************************************************************************/
7556
7557 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7558                                        const struct auth_session_info *session_info,
7559                                        struct messaging_context *msg_ctx,
7560                                        const char *servername,
7561                                        const char *architecture,
7562                                        uint32_t level,
7563                                        union spoolss_DriverInfo **info_p,
7564                                        uint32_t *count_p)
7565 {
7566         uint32_t a,i;
7567         WERROR result = WERR_OK;
7568
7569         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7570
7571                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7572
7573                         union spoolss_DriverInfo *info = NULL;
7574                         uint32_t count = 0;
7575
7576                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7577                                                                           session_info,
7578                                                                           msg_ctx,
7579                                                                           servername,
7580                                                                           archi_table[a].long_archi,
7581                                                                           level,
7582                                                                           &info,
7583                                                                           &count);
7584                         if (!W_ERROR_IS_OK(result)) {
7585                                 continue;
7586                         }
7587
7588                         for (i=0; i < count; i++) {
7589                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7590                                              info[i], info_p, count_p);
7591                         }
7592                 }
7593
7594                 return result;
7595         }
7596
7597         return enumprinterdrivers_level_by_architecture(mem_ctx,
7598                                                         session_info,
7599                                                         msg_ctx,
7600                                                         servername,
7601                                                         architecture,
7602                                                         level,
7603                                                         info_p,
7604                                                         count_p);
7605 }
7606
7607 /****************************************************************
7608  _spoolss_EnumPrinterDrivers
7609 ****************************************************************/
7610
7611 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7612                                    struct spoolss_EnumPrinterDrivers *r)
7613 {
7614         const char *cservername;
7615         WERROR result;
7616
7617         /* that's an [in out] buffer */
7618
7619         if (!r->in.buffer && (r->in.offered != 0)) {
7620                 return WERR_INVALID_PARAM;
7621         }
7622
7623         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7624
7625         *r->out.needed = 0;
7626         *r->out.count = 0;
7627         *r->out.info = NULL;
7628
7629         cservername = canon_servername(r->in.server);
7630
7631         if (!is_myname_or_ipaddr(cservername)) {
7632                 return WERR_UNKNOWN_PRINTER_DRIVER;
7633         }
7634
7635         result = enumprinterdrivers_level(p->mem_ctx,
7636                                           get_session_info_system(),
7637                                           p->msg_ctx,
7638                                           cservername,
7639                                           r->in.environment,
7640                                           r->in.level,
7641                                           r->out.info,
7642                                           r->out.count);
7643         if (!W_ERROR_IS_OK(result)) {
7644                 return result;
7645         }
7646
7647         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7648                                                      spoolss_EnumPrinterDrivers,
7649                                                      *r->out.info, r->in.level,
7650                                                      *r->out.count);
7651         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7652         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7653
7654         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7655 }
7656
7657 /****************************************************************
7658  _spoolss_EnumForms
7659 ****************************************************************/
7660
7661 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7662                           struct spoolss_EnumForms *r)
7663 {
7664         WERROR result;
7665
7666         *r->out.count = 0;
7667         *r->out.needed = 0;
7668         *r->out.info = NULL;
7669
7670         /* that's an [in out] buffer */
7671
7672         if (!r->in.buffer && (r->in.offered != 0) ) {
7673                 return WERR_INVALID_PARAM;
7674         }
7675
7676         DEBUG(4,("_spoolss_EnumForms\n"));
7677         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7678         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7679
7680         switch (r->in.level) {
7681         case 1:
7682                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7683                                                    get_session_info_system(),
7684                                                    p->msg_ctx,
7685                                                    r->out.count,
7686                                                    r->out.info);
7687                 break;
7688         default:
7689                 result = WERR_UNKNOWN_LEVEL;
7690                 break;
7691         }
7692
7693         if (!W_ERROR_IS_OK(result)) {
7694                 return result;
7695         }
7696
7697         if (*r->out.count == 0) {
7698                 return WERR_NO_MORE_ITEMS;
7699         }
7700
7701         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7702                                                      spoolss_EnumForms,
7703                                                      *r->out.info, r->in.level,
7704                                                      *r->out.count);
7705         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7706         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7707
7708         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7709 }
7710
7711 /****************************************************************
7712  _spoolss_GetForm
7713 ****************************************************************/
7714
7715 WERROR _spoolss_GetForm(struct pipes_struct *p,
7716                         struct spoolss_GetForm *r)
7717 {
7718         WERROR result;
7719
7720         /* that's an [in out] buffer */
7721
7722         if (!r->in.buffer && (r->in.offered != 0)) {
7723                 return WERR_INVALID_PARAM;
7724         }
7725
7726         DEBUG(4,("_spoolss_GetForm\n"));
7727         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7728         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7729
7730         switch (r->in.level) {
7731         case 1:
7732                 result = winreg_printer_getform1_internal(p->mem_ctx,
7733                                                  get_session_info_system(),
7734                                                  p->msg_ctx,
7735                                                  r->in.form_name,
7736                                                  &r->out.info->info1);
7737                 break;
7738         default:
7739                 result = WERR_UNKNOWN_LEVEL;
7740                 break;
7741         }
7742
7743         if (!W_ERROR_IS_OK(result)) {
7744                 TALLOC_FREE(r->out.info);
7745                 return result;
7746         }
7747
7748         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7749                                                r->out.info, r->in.level);
7750         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7751
7752         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7753 }
7754
7755 /****************************************************************************
7756 ****************************************************************************/
7757
7758 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7759                           struct spoolss_PortInfo1 *r,
7760                           const char *name)
7761 {
7762         r->port_name = talloc_strdup(mem_ctx, name);
7763         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7764
7765         return WERR_OK;
7766 }
7767
7768 /****************************************************************************
7769  TODO: This probably needs distinguish between TCP/IP and Local ports
7770  somehow.
7771 ****************************************************************************/
7772
7773 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7774                           struct spoolss_PortInfo2 *r,
7775                           const char *name)
7776 {
7777         r->port_name = talloc_strdup(mem_ctx, name);
7778         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7779
7780         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7781         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7782
7783         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7784         W_ERROR_HAVE_NO_MEMORY(r->description);
7785
7786         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7787         r->reserved = 0;
7788
7789         return WERR_OK;
7790 }
7791
7792
7793 /****************************************************************************
7794  wrapper around the enumer ports command
7795 ****************************************************************************/
7796
7797 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7798 {
7799         char *cmd = lp_enumports_cmd(talloc_tos());
7800         char **qlines = NULL;
7801         char *command = NULL;
7802         int numlines;
7803         int ret;
7804         int fd;
7805
7806         *count = 0;
7807         *lines = NULL;
7808
7809         /* if no hook then just fill in the default port */
7810
7811         if ( !*cmd ) {
7812                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7813                         return WERR_NOMEM;
7814                 }
7815                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7816                         TALLOC_FREE(qlines);
7817                         return WERR_NOMEM;
7818                 }
7819                 qlines[1] = NULL;
7820                 numlines = 1;
7821         }
7822         else {
7823                 /* we have a valid enumport command */
7824
7825                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7826                 if (!command) {
7827                         return WERR_NOMEM;
7828                 }
7829
7830                 DEBUG(10,("Running [%s]\n", command));
7831                 ret = smbrun(command, &fd);
7832                 DEBUG(10,("Returned [%d]\n", ret));
7833                 TALLOC_FREE(command);
7834                 if (ret != 0) {
7835                         if (fd != -1) {
7836                                 close(fd);
7837                         }
7838                         return WERR_ACCESS_DENIED;
7839                 }
7840
7841                 numlines = 0;
7842                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7843                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7844                 close(fd);
7845         }
7846
7847         *count = numlines;
7848         *lines = qlines;
7849
7850         return WERR_OK;
7851 }
7852
7853 /****************************************************************************
7854  enumports level 1.
7855 ****************************************************************************/
7856
7857 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7858                                 union spoolss_PortInfo **info_p,
7859                                 uint32_t *count)
7860 {
7861         union spoolss_PortInfo *info = NULL;
7862         int i=0;
7863         WERROR result = WERR_OK;
7864         char **qlines = NULL;
7865         int numlines = 0;
7866
7867         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7868         if (!W_ERROR_IS_OK(result)) {
7869                 goto out;
7870         }
7871
7872         if (numlines) {
7873                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7874                 if (!info) {
7875                         DEBUG(10,("Returning WERR_NOMEM\n"));
7876                         result = WERR_NOMEM;
7877                         goto out;
7878                 }
7879
7880                 for (i=0; i<numlines; i++) {
7881                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7882                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7883                         if (!W_ERROR_IS_OK(result)) {
7884                                 goto out;
7885                         }
7886                 }
7887         }
7888         TALLOC_FREE(qlines);
7889
7890 out:
7891         if (!W_ERROR_IS_OK(result)) {
7892                 TALLOC_FREE(info);
7893                 TALLOC_FREE(qlines);
7894                 *count = 0;
7895                 *info_p = NULL;
7896                 return result;
7897         }
7898
7899         *info_p = info;
7900         *count = numlines;
7901
7902         return WERR_OK;
7903 }
7904
7905 /****************************************************************************
7906  enumports level 2.
7907 ****************************************************************************/
7908
7909 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7910                                 union spoolss_PortInfo **info_p,
7911                                 uint32_t *count)
7912 {
7913         union spoolss_PortInfo *info = NULL;
7914         int i=0;
7915         WERROR result = WERR_OK;
7916         char **qlines = NULL;
7917         int numlines = 0;
7918
7919         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7920         if (!W_ERROR_IS_OK(result)) {
7921                 goto out;
7922         }
7923
7924         if (numlines) {
7925                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7926                 if (!info) {
7927                         DEBUG(10,("Returning WERR_NOMEM\n"));
7928                         result = WERR_NOMEM;
7929                         goto out;
7930                 }
7931
7932                 for (i=0; i<numlines; i++) {
7933                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7934                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7935                         if (!W_ERROR_IS_OK(result)) {
7936                                 goto out;
7937                         }
7938                 }
7939         }
7940         TALLOC_FREE(qlines);
7941
7942 out:
7943         if (!W_ERROR_IS_OK(result)) {
7944                 TALLOC_FREE(info);
7945                 TALLOC_FREE(qlines);
7946                 *count = 0;
7947                 *info_p = NULL;
7948                 return result;
7949         }
7950
7951         *info_p = info;
7952         *count = numlines;
7953
7954         return WERR_OK;
7955 }
7956
7957 /****************************************************************
7958  _spoolss_EnumPorts
7959 ****************************************************************/
7960
7961 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7962                           struct spoolss_EnumPorts *r)
7963 {
7964         WERROR result;
7965
7966         /* that's an [in out] buffer */
7967
7968         if (!r->in.buffer && (r->in.offered != 0)) {
7969                 return WERR_INVALID_PARAM;
7970         }
7971
7972         DEBUG(4,("_spoolss_EnumPorts\n"));
7973
7974         *r->out.count = 0;
7975         *r->out.needed = 0;
7976         *r->out.info = NULL;
7977
7978         switch (r->in.level) {
7979         case 1:
7980                 result = enumports_level_1(p->mem_ctx, r->out.info,
7981                                            r->out.count);
7982                 break;
7983         case 2:
7984                 result = enumports_level_2(p->mem_ctx, r->out.info,
7985                                            r->out.count);
7986                 break;
7987         default:
7988                 return WERR_UNKNOWN_LEVEL;
7989         }
7990
7991         if (!W_ERROR_IS_OK(result)) {
7992                 return result;
7993         }
7994
7995         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7996                                                      spoolss_EnumPorts,
7997                                                      *r->out.info, r->in.level,
7998                                                      *r->out.count);
7999         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8000         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8001
8002         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8003 }
8004
8005 /****************************************************************************
8006 ****************************************************************************/
8007
8008 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8009                                            const char *server,
8010                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8011                                            struct spoolss_DeviceMode *devmode,
8012                                            struct security_descriptor *secdesc,
8013                                            struct spoolss_UserLevelCtr *user_ctr,
8014                                            struct policy_handle *handle)
8015 {
8016         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8017         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8018         int     snum;
8019         WERROR err = WERR_OK;
8020
8021         /* samba does not have a concept of local, non-shared printers yet, so
8022          * make sure we always setup sharename - gd */
8023         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8024             (info2->printername != NULL && info2->printername[0] != '\0')) {
8025                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8026                         "no sharename has been set, setting printername %s as sharename\n",
8027                         info2->printername));
8028                 info2->sharename = info2->printername;
8029         }
8030
8031         /* check to see if the printer already exists */
8032         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8033                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8034                         info2->sharename));
8035                 return WERR_PRINTER_ALREADY_EXISTS;
8036         }
8037
8038         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8039                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8040                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8041                                 info2->printername));
8042                         return WERR_PRINTER_ALREADY_EXISTS;
8043                 }
8044         }
8045
8046         /* validate printer info struct */
8047         if (!info2->printername || strlen(info2->printername) == 0) {
8048                 return WERR_INVALID_PRINTER_NAME;
8049         }
8050         if (!info2->portname || strlen(info2->portname) == 0) {
8051                 return WERR_UNKNOWN_PORT;
8052         }
8053         if (!info2->drivername || strlen(info2->drivername) == 0) {
8054                 return WERR_UNKNOWN_PRINTER_DRIVER;
8055         }
8056         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8057                 return WERR_UNKNOWN_PRINTPROCESSOR;
8058         }
8059
8060         /* FIXME!!!  smbd should check to see if the driver is installed before
8061            trying to add a printer like this  --jerry */
8062
8063         if (*lp_addprinter_cmd(talloc_tos()) ) {
8064                 char *raddr;
8065
8066                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8067                                                          p->mem_ctx);
8068                 if (raddr == NULL) {
8069                         return WERR_NOMEM;
8070                 }
8071
8072                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8073                                        info2, raddr,
8074                                        p->msg_ctx) ) {
8075                         return WERR_ACCESS_DENIED;
8076                 }
8077         } else {
8078                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8079                         "smb.conf parameter \"addprinter command\" is defined. This "
8080                         "parameter must exist for this call to succeed\n",
8081                         info2->sharename ));
8082         }
8083
8084         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8085                 return WERR_ACCESS_DENIED;
8086         }
8087
8088         /* you must be a printer admin to add a new printer */
8089         if (!print_access_check(p->session_info,
8090                                 p->msg_ctx,
8091                                 snum,
8092                                 PRINTER_ACCESS_ADMINISTER)) {
8093                 return WERR_ACCESS_DENIED;
8094         }
8095
8096         /*
8097          * Do sanity check on the requested changes for Samba.
8098          */
8099
8100         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8101                 return WERR_INVALID_PARAM;
8102         }
8103
8104         if (devmode == NULL) {
8105                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8106         }
8107
8108         err = update_dsspooler(p->mem_ctx,
8109                                get_session_info_system(),
8110                                p->msg_ctx,
8111                                0,
8112                                info2,
8113                                NULL);
8114         if (!W_ERROR_IS_OK(err)) {
8115                 return err;
8116         }
8117
8118         err = winreg_update_printer_internal(p->mem_ctx,
8119                                     get_session_info_system(),
8120                                     p->msg_ctx,
8121                                     info2->sharename,
8122                                     info2_mask,
8123                                     info2,
8124                                     devmode,
8125                                     secdesc);
8126         if (!W_ERROR_IS_OK(err)) {
8127                 return err;
8128         }
8129
8130         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8131         if (!W_ERROR_IS_OK(err)) {
8132                 /* Handle open failed - remove addition. */
8133                 ZERO_STRUCTP(handle);
8134                 return err;
8135         }
8136
8137         return WERR_OK;
8138 }
8139
8140 /****************************************************************
8141  _spoolss_AddPrinterEx
8142 ****************************************************************/
8143
8144 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8145                              struct spoolss_AddPrinterEx *r)
8146 {
8147         switch (r->in.info_ctr->level) {
8148         case 1:
8149                 /* we don't handle yet */
8150                 /* but I know what to do ... */
8151                 return WERR_UNKNOWN_LEVEL;
8152         case 2:
8153                 return spoolss_addprinterex_level_2(p, r->in.server,
8154                                                     r->in.info_ctr,
8155                                                     r->in.devmode_ctr->devmode,
8156                                                     r->in.secdesc_ctr->sd,
8157                                                     r->in.userlevel_ctr,
8158                                                     r->out.handle);
8159         default:
8160                 return WERR_UNKNOWN_LEVEL;
8161         }
8162 }
8163
8164 /****************************************************************
8165  _spoolss_AddPrinter
8166 ****************************************************************/
8167
8168 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8169                            struct spoolss_AddPrinter *r)
8170 {
8171         struct spoolss_AddPrinterEx a;
8172         struct spoolss_UserLevelCtr userlevel_ctr;
8173
8174         ZERO_STRUCT(userlevel_ctr);
8175
8176         userlevel_ctr.level = 1;
8177
8178         a.in.server             = r->in.server;
8179         a.in.info_ctr           = r->in.info_ctr;
8180         a.in.devmode_ctr        = r->in.devmode_ctr;
8181         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8182         a.in.userlevel_ctr      = &userlevel_ctr;
8183         a.out.handle            = r->out.handle;
8184
8185         return _spoolss_AddPrinterEx(p, &a);
8186 }
8187
8188 /****************************************************************
8189  _spoolss_AddPrinterDriverEx
8190 ****************************************************************/
8191
8192 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8193                                    struct spoolss_AddPrinterDriverEx *r)
8194 {
8195         WERROR err = WERR_OK;
8196         const char *driver_name = NULL;
8197         uint32_t version;
8198         const char *fn;
8199
8200         switch (p->opnum) {
8201                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8202                         fn = "_spoolss_AddPrinterDriver";
8203                         break;
8204                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8205                         fn = "_spoolss_AddPrinterDriverEx";
8206                         break;
8207                 default:
8208                         return WERR_INVALID_PARAM;
8209         }
8210
8211         /*
8212          * we only support the semantics of AddPrinterDriver()
8213          * i.e. only copy files that are newer than existing ones
8214          */
8215
8216         if (r->in.flags == 0) {
8217                 return WERR_INVALID_PARAM;
8218         }
8219
8220         if (r->in.flags != APD_COPY_NEW_FILES) {
8221                 return WERR_ACCESS_DENIED;
8222         }
8223
8224         /* FIXME */
8225         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8226                 /* Clever hack from Martin Zielinski <mz@seh.de>
8227                  * to allow downgrade from level 8 (Vista).
8228                  */
8229                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8230                         r->in.info_ctr->level));
8231                 return WERR_UNKNOWN_LEVEL;
8232         }
8233
8234         DEBUG(5,("Cleaning driver's information\n"));
8235         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8236         if (!W_ERROR_IS_OK(err))
8237                 goto done;
8238
8239         DEBUG(5,("Moving driver to final destination\n"));
8240         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8241         if (!W_ERROR_IS_OK(err)) {
8242                 goto done;
8243         }
8244
8245         err = winreg_add_driver_internal(p->mem_ctx,
8246                                 get_session_info_system(),
8247                                 p->msg_ctx,
8248                                 r->in.info_ctr,
8249                                 &driver_name,
8250                                 &version);
8251         if (!W_ERROR_IS_OK(err)) {
8252                 goto done;
8253         }
8254
8255         /*
8256          * I think this is where he DrvUpgradePrinter() hook would be
8257          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8258          * server.  Right now, we just need to send ourselves a message
8259          * to update each printer bound to this driver.   --jerry
8260          */
8261
8262         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8263                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8264                         fn, driver_name));
8265         }
8266
8267 done:
8268         return err;
8269 }
8270
8271 /****************************************************************
8272  _spoolss_AddPrinterDriver
8273 ****************************************************************/
8274
8275 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8276                                  struct spoolss_AddPrinterDriver *r)
8277 {
8278         struct spoolss_AddPrinterDriverEx a;
8279
8280         switch (r->in.info_ctr->level) {
8281         case 2:
8282         case 3:
8283         case 4:
8284         case 5:
8285                 break;
8286         default:
8287                 return WERR_UNKNOWN_LEVEL;
8288         }
8289
8290         a.in.servername         = r->in.servername;
8291         a.in.info_ctr           = r->in.info_ctr;
8292         a.in.flags              = APD_COPY_NEW_FILES;
8293
8294         return _spoolss_AddPrinterDriverEx(p, &a);
8295 }
8296
8297 /****************************************************************************
8298 ****************************************************************************/
8299
8300 struct _spoolss_paths {
8301         int type;
8302         const char *share;
8303         const char *dir;
8304 };
8305
8306 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8307
8308 static const struct _spoolss_paths spoolss_paths[]= {
8309         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8310         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8311 };
8312
8313 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8314                                           const char *servername,
8315                                           const char *environment,
8316                                           int component,
8317                                           char **path)
8318 {
8319         const char *pservername = NULL;
8320         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8321         const char *short_archi;
8322
8323         *path = NULL;
8324
8325         /* environment may be empty */
8326         if (environment && strlen(environment)) {
8327                 long_archi = environment;
8328         }
8329
8330         /* servername may be empty */
8331         if (servername && strlen(servername)) {
8332                 pservername = canon_servername(servername);
8333
8334                 if (!is_myname_or_ipaddr(pservername)) {
8335                         return WERR_INVALID_PARAM;
8336                 }
8337         }
8338
8339         if (!(short_archi = get_short_archi(long_archi))) {
8340                 return WERR_INVALID_ENVIRONMENT;
8341         }
8342
8343         switch (component) {
8344         case SPOOLSS_PRTPROCS_PATH:
8345         case SPOOLSS_DRIVER_PATH:
8346                 if (pservername) {
8347                         *path = talloc_asprintf(mem_ctx,
8348                                         "\\\\%s\\%s\\%s",
8349                                         pservername,
8350                                         spoolss_paths[component].share,
8351                                         short_archi);
8352                 } else {
8353                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8354                                         SPOOLSS_DEFAULT_SERVER_PATH,
8355                                         spoolss_paths[component].dir,
8356                                         short_archi);
8357                 }
8358                 break;
8359         default:
8360                 return WERR_INVALID_PARAM;
8361         }
8362
8363         if (!*path) {
8364                 return WERR_NOMEM;
8365         }
8366
8367         return WERR_OK;
8368 }
8369
8370 /****************************************************************************
8371 ****************************************************************************/
8372
8373 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8374                                           const char *servername,
8375                                           const char *environment,
8376                                           struct spoolss_DriverDirectoryInfo1 *r)
8377 {
8378         WERROR werr;
8379         char *path = NULL;
8380
8381         werr = compose_spoolss_server_path(mem_ctx,
8382                                            servername,
8383                                            environment,
8384                                            SPOOLSS_DRIVER_PATH,
8385                                            &path);
8386         if (!W_ERROR_IS_OK(werr)) {
8387                 return werr;
8388         }
8389
8390         DEBUG(4,("printer driver directory: [%s]\n", path));
8391
8392         r->directory_name = path;
8393
8394         return WERR_OK;
8395 }
8396
8397 /****************************************************************
8398  _spoolss_GetPrinterDriverDirectory
8399 ****************************************************************/
8400
8401 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8402                                           struct spoolss_GetPrinterDriverDirectory *r)
8403 {
8404         WERROR werror;
8405
8406         /* that's an [in out] buffer */
8407
8408         if (!r->in.buffer && (r->in.offered != 0)) {
8409                 return WERR_INVALID_PARAM;
8410         }
8411
8412         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8413                 r->in.level));
8414
8415         *r->out.needed = 0;
8416
8417         /* r->in.level is ignored */
8418
8419         werror = getprinterdriverdir_level_1(p->mem_ctx,
8420                                              r->in.server,
8421                                              r->in.environment,
8422                                              &r->out.info->info1);
8423         if (!W_ERROR_IS_OK(werror)) {
8424                 TALLOC_FREE(r->out.info);
8425                 return werror;
8426         }
8427
8428         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8429                                                r->out.info, r->in.level);
8430         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8431
8432         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8433 }
8434
8435 /****************************************************************
8436  _spoolss_EnumPrinterData
8437 ****************************************************************/
8438
8439 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8440                                 struct spoolss_EnumPrinterData *r)
8441 {
8442         WERROR result;
8443         struct spoolss_EnumPrinterDataEx r2;
8444         uint32_t count;
8445         struct spoolss_PrinterEnumValues *info, *val = NULL;
8446         uint32_t needed;
8447
8448         r2.in.handle    = r->in.handle;
8449         r2.in.key_name  = "PrinterDriverData";
8450         r2.in.offered   = 0;
8451         r2.out.count    = &count;
8452         r2.out.info     = &info;
8453         r2.out.needed   = &needed;
8454
8455         result = _spoolss_EnumPrinterDataEx(p, &r2);
8456         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8457                 r2.in.offered = needed;
8458                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8459         }
8460         if (!W_ERROR_IS_OK(result)) {
8461                 return result;
8462         }
8463
8464         /*
8465          * The NT machine wants to know the biggest size of value and data
8466          *
8467          * cf: MSDN EnumPrinterData remark section
8468          */
8469
8470         if (!r->in.value_offered && !r->in.data_offered) {
8471                 uint32_t biggest_valuesize = 0;
8472                 uint32_t biggest_datasize = 0;
8473                 int i, name_length;
8474
8475                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8476
8477                 for (i=0; i<count; i++) {
8478
8479                         name_length = strlen(info[i].value_name);
8480                         if (strlen(info[i].value_name) > biggest_valuesize) {
8481                                 biggest_valuesize = name_length;
8482                         }
8483
8484                         if (info[i].data_length > biggest_datasize) {
8485                                 biggest_datasize = info[i].data_length;
8486                         }
8487
8488                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8489                                 biggest_datasize));
8490                 }
8491
8492                 /* the value is an UNICODE string but real_value_size is the length
8493                    in bytes including the trailing 0 */
8494
8495                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8496                 *r->out.data_needed  = biggest_datasize;
8497
8498                 DEBUG(6,("final values: [%d], [%d]\n",
8499                         *r->out.value_needed, *r->out.data_needed));
8500
8501                 return WERR_OK;
8502         }
8503
8504         if (r->in.enum_index < count) {
8505                 val = &info[r->in.enum_index];
8506         }
8507
8508         if (val == NULL) {
8509                 /* out_value should default to "" or else NT4 has
8510                    problems unmarshalling the response */
8511
8512                 if (r->in.value_offered) {
8513                         *r->out.value_needed = 1;
8514                         r->out.value_name = talloc_strdup(r, "");
8515                         if (!r->out.value_name) {
8516                                 return WERR_NOMEM;
8517                         }
8518                 } else {
8519                         r->out.value_name = NULL;
8520                         *r->out.value_needed = 0;
8521                 }
8522
8523                 /* the data is counted in bytes */
8524
8525                 *r->out.data_needed = r->in.data_offered;
8526
8527                 result = WERR_NO_MORE_ITEMS;
8528         } else {
8529                 /*
8530                  * the value is:
8531                  * - counted in bytes in the request
8532                  * - counted in UNICODE chars in the max reply
8533                  * - counted in bytes in the real size
8534                  *
8535                  * take a pause *before* coding not *during* coding
8536                  */
8537
8538                 /* name */
8539                 if (r->in.value_offered) {
8540                         r->out.value_name = talloc_strdup(r, val->value_name);
8541                         if (!r->out.value_name) {
8542                                 return WERR_NOMEM;
8543                         }
8544                         *r->out.value_needed = val->value_name_len;
8545                 } else {
8546                         r->out.value_name = NULL;
8547                         *r->out.value_needed = 0;
8548                 }
8549
8550                 /* type */
8551
8552                 *r->out.type = val->type;
8553
8554                 /* data - counted in bytes */
8555
8556                 /*
8557                  * See the section "Dynamically Typed Query Parameters"
8558                  * in MS-RPRN.
8559                  */
8560
8561                 if (r->out.data && val->data && val->data->data &&
8562                                 val->data_length && r->in.data_offered) {
8563                         memcpy(r->out.data, val->data->data,
8564                                 MIN(val->data_length,r->in.data_offered));
8565                 }
8566
8567                 *r->out.data_needed = val->data_length;
8568
8569                 result = WERR_OK;
8570         }
8571
8572         return result;
8573 }
8574
8575 /****************************************************************
8576  _spoolss_SetPrinterData
8577 ****************************************************************/
8578
8579 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8580                                struct spoolss_SetPrinterData *r)
8581 {
8582         struct spoolss_SetPrinterDataEx r2;
8583
8584         r2.in.handle            = r->in.handle;
8585         r2.in.key_name          = "PrinterDriverData";
8586         r2.in.value_name        = r->in.value_name;
8587         r2.in.type              = r->in.type;
8588         r2.in.data              = r->in.data;
8589         r2.in.offered           = r->in.offered;
8590
8591         return _spoolss_SetPrinterDataEx(p, &r2);
8592 }
8593
8594 /****************************************************************
8595  _spoolss_ResetPrinter
8596 ****************************************************************/
8597
8598 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8599                              struct spoolss_ResetPrinter *r)
8600 {
8601         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8602         int             snum;
8603
8604         DEBUG(5,("_spoolss_ResetPrinter\n"));
8605
8606         /*
8607          * All we do is to check to see if the handle and queue is valid.
8608          * This call really doesn't mean anything to us because we only
8609          * support RAW printing.   --jerry
8610          */
8611
8612         if (!Printer) {
8613                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8614                         OUR_HANDLE(r->in.handle)));
8615                 return WERR_BADFID;
8616         }
8617
8618         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8619                 return WERR_BADFID;
8620
8621
8622         /* blindly return success */
8623         return WERR_OK;
8624 }
8625
8626 /****************************************************************
8627  _spoolss_DeletePrinterData
8628 ****************************************************************/
8629
8630 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8631                                   struct spoolss_DeletePrinterData *r)
8632 {
8633         struct spoolss_DeletePrinterDataEx r2;
8634
8635         r2.in.handle            = r->in.handle;
8636         r2.in.key_name          = "PrinterDriverData";
8637         r2.in.value_name        = r->in.value_name;
8638
8639         return _spoolss_DeletePrinterDataEx(p, &r2);
8640 }
8641
8642 /****************************************************************
8643  _spoolss_AddForm
8644 ****************************************************************/
8645
8646 WERROR _spoolss_AddForm(struct pipes_struct *p,
8647                         struct spoolss_AddForm *r)
8648 {
8649         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8650         int snum = -1;
8651         WERROR status = WERR_OK;
8652         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8653         struct dcerpc_binding_handle *b;
8654         TALLOC_CTX *tmp_ctx = NULL;
8655
8656         DEBUG(5,("_spoolss_AddForm\n"));
8657
8658         if (!Printer) {
8659                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8660                         OUR_HANDLE(r->in.handle)));
8661                 return WERR_BADFID;
8662         }
8663
8664         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8665            and not a printer admin, then fail */
8666
8667         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8668             !security_token_has_privilege(p->session_info->security_token,
8669                                           SEC_PRIV_PRINT_OPERATOR)) {
8670                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8671                 return WERR_ACCESS_DENIED;
8672         }
8673
8674         switch (form->flags) {
8675         case SPOOLSS_FORM_USER:
8676         case SPOOLSS_FORM_BUILTIN:
8677         case SPOOLSS_FORM_PRINTER:
8678                 break;
8679         default:
8680                 return WERR_INVALID_PARAM;
8681         }
8682
8683         tmp_ctx = talloc_new(p->mem_ctx);
8684         if (!tmp_ctx) {
8685                 return WERR_NOMEM;
8686         }
8687
8688         status = winreg_printer_binding_handle(tmp_ctx,
8689                                                get_session_info_system(),
8690                                                p->msg_ctx,
8691                                                &b);
8692         if (!W_ERROR_IS_OK(status)) {
8693                 goto done;
8694         }
8695
8696         status = winreg_printer_addform1(tmp_ctx, b, form);
8697         if (!W_ERROR_IS_OK(status)) {
8698                 goto done;
8699         }
8700
8701         /*
8702          * ChangeID must always be set if this is a printer
8703          */
8704         if (Printer->printer_type == SPLHND_PRINTER) {
8705                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8706                         status = WERR_BADFID;
8707                         goto done;
8708                 }
8709
8710                 status = winreg_printer_update_changeid(tmp_ctx, b,
8711                                                         lp_const_servicename(snum));
8712         }
8713
8714 done:
8715         talloc_free(tmp_ctx);
8716         return status;
8717 }
8718
8719 /****************************************************************
8720  _spoolss_DeleteForm
8721 ****************************************************************/
8722
8723 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8724                            struct spoolss_DeleteForm *r)
8725 {
8726         const char *form_name = r->in.form_name;
8727         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8728         int snum = -1;
8729         WERROR status = WERR_OK;
8730         struct dcerpc_binding_handle *b;
8731         TALLOC_CTX *tmp_ctx = NULL;
8732
8733         DEBUG(5,("_spoolss_DeleteForm\n"));
8734
8735         if (!Printer) {
8736                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8737                         OUR_HANDLE(r->in.handle)));
8738                 return WERR_BADFID;
8739         }
8740
8741         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8742             !security_token_has_privilege(p->session_info->security_token,
8743                                           SEC_PRIV_PRINT_OPERATOR)) {
8744                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8745                 return WERR_ACCESS_DENIED;
8746         }
8747
8748         tmp_ctx = talloc_new(p->mem_ctx);
8749         if (!tmp_ctx) {
8750                 return WERR_NOMEM;
8751         }
8752
8753         status = winreg_printer_binding_handle(tmp_ctx,
8754                                                get_session_info_system(),
8755                                                p->msg_ctx,
8756                                                &b);
8757         if (!W_ERROR_IS_OK(status)) {
8758                 goto done;
8759         }
8760
8761         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8762         if (!W_ERROR_IS_OK(status)) {
8763                 goto done;
8764         }
8765
8766         /*
8767          * ChangeID must always be set if this is a printer
8768          */
8769         if (Printer->printer_type == SPLHND_PRINTER) {
8770                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8771                         status = WERR_BADFID;
8772                         goto done;
8773                 }
8774
8775                 status = winreg_printer_update_changeid(tmp_ctx, b,
8776                                                         lp_const_servicename(snum));
8777         }
8778
8779 done:
8780         talloc_free(tmp_ctx);
8781         return status;
8782 }
8783
8784 /****************************************************************
8785  _spoolss_SetForm
8786 ****************************************************************/
8787
8788 WERROR _spoolss_SetForm(struct pipes_struct *p,
8789                         struct spoolss_SetForm *r)
8790 {
8791         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8792         const char *form_name = r->in.form_name;
8793         int snum = -1;
8794         WERROR status = WERR_OK;
8795         struct dcerpc_binding_handle *b;
8796         TALLOC_CTX *tmp_ctx = NULL;
8797
8798         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8799
8800         DEBUG(5,("_spoolss_SetForm\n"));
8801
8802         if (!Printer) {
8803                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8804                         OUR_HANDLE(r->in.handle)));
8805                 return WERR_BADFID;
8806         }
8807
8808         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8809            and not a printer admin, then fail */
8810
8811         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8812              !security_token_has_privilege(p->session_info->security_token,
8813                                            SEC_PRIV_PRINT_OPERATOR)) {
8814                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8815                 return WERR_ACCESS_DENIED;
8816         }
8817
8818         tmp_ctx = talloc_new(p->mem_ctx);
8819         if (!tmp_ctx) {
8820                 return WERR_NOMEM;
8821         }
8822
8823         status = winreg_printer_binding_handle(tmp_ctx,
8824                                                get_session_info_system(),
8825                                                p->msg_ctx,
8826                                                &b);
8827         if (!W_ERROR_IS_OK(status)) {
8828                 goto done;
8829         }
8830
8831         status = winreg_printer_setform1(tmp_ctx, b,
8832                                          form_name,
8833                                          form);
8834         if (!W_ERROR_IS_OK(status)) {
8835                 goto done;
8836         }
8837
8838         /*
8839          * ChangeID must always be set if this is a printer
8840          */
8841         if (Printer->printer_type == SPLHND_PRINTER) {
8842                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8843                         status = WERR_BADFID;
8844                         goto done;
8845                 }
8846
8847                 status = winreg_printer_update_changeid(tmp_ctx, b,
8848                                                         lp_const_servicename(snum));
8849         }
8850
8851 done:
8852         talloc_free(tmp_ctx);
8853         return status;
8854 }
8855
8856 /****************************************************************************
8857  fill_print_processor1
8858 ****************************************************************************/
8859
8860 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8861                                     struct spoolss_PrintProcessorInfo1 *r,
8862                                     const char *print_processor_name)
8863 {
8864         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8865         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8866
8867         return WERR_OK;
8868 }
8869
8870 /****************************************************************************
8871  enumprintprocessors level 1.
8872 ****************************************************************************/
8873
8874 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8875                                           union spoolss_PrintProcessorInfo **info_p,
8876                                           uint32_t *count)
8877 {
8878         union spoolss_PrintProcessorInfo *info;
8879         WERROR result;
8880
8881         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8882         W_ERROR_HAVE_NO_MEMORY(info);
8883
8884         *count = 1;
8885
8886         result = fill_print_processor1(info, &info[0].info1, "winprint");
8887         if (!W_ERROR_IS_OK(result)) {
8888                 goto out;
8889         }
8890
8891  out:
8892         if (!W_ERROR_IS_OK(result)) {
8893                 TALLOC_FREE(info);
8894                 *count = 0;
8895                 return result;
8896         }
8897
8898         *info_p = info;
8899
8900         return WERR_OK;
8901 }
8902
8903 /****************************************************************
8904  _spoolss_EnumPrintProcessors
8905 ****************************************************************/
8906
8907 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8908                                     struct spoolss_EnumPrintProcessors *r)
8909 {
8910         WERROR result;
8911
8912         /* that's an [in out] buffer */
8913
8914         if (!r->in.buffer && (r->in.offered != 0)) {
8915                 return WERR_INVALID_PARAM;
8916         }
8917
8918         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8919
8920         /*
8921          * Enumerate the print processors ...
8922          *
8923          * Just reply with "winprint", to keep NT happy
8924          * and I can use my nice printer checker.
8925          */
8926
8927         *r->out.count = 0;
8928         *r->out.needed = 0;
8929         *r->out.info = NULL;
8930
8931         if (!get_short_archi(r->in.environment)) {
8932                 return WERR_INVALID_ENVIRONMENT;
8933         }
8934
8935         switch (r->in.level) {
8936         case 1:
8937                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8938                                                      r->out.count);
8939                 break;
8940         default:
8941                 return WERR_UNKNOWN_LEVEL;
8942         }
8943
8944         if (!W_ERROR_IS_OK(result)) {
8945                 return result;
8946         }
8947
8948         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8949                                                      spoolss_EnumPrintProcessors,
8950                                                      *r->out.info, r->in.level,
8951                                                      *r->out.count);
8952         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8953         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8954
8955         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8956 }
8957
8958 /****************************************************************************
8959  fill_printprocdatatype1
8960 ****************************************************************************/
8961
8962 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8963                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8964                                       const char *name_array)
8965 {
8966         r->name_array = talloc_strdup(mem_ctx, name_array);
8967         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8968
8969         return WERR_OK;
8970 }
8971
8972 /****************************************************************************
8973  enumprintprocdatatypes level 1.
8974 ****************************************************************************/
8975
8976 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8977                                              union spoolss_PrintProcDataTypesInfo **info_p,
8978                                              uint32_t *count)
8979 {
8980         WERROR result;
8981         union spoolss_PrintProcDataTypesInfo *info;
8982
8983         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8984         W_ERROR_HAVE_NO_MEMORY(info);
8985
8986         *count = 1;
8987
8988         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8989         if (!W_ERROR_IS_OK(result)) {
8990                 goto out;
8991         }
8992
8993  out:
8994         if (!W_ERROR_IS_OK(result)) {
8995                 TALLOC_FREE(info);
8996                 *count = 0;
8997                 return result;
8998         }
8999
9000         *info_p = info;
9001
9002         return WERR_OK;
9003 }
9004
9005 /****************************************************************
9006  _spoolss_EnumPrintProcDataTypes
9007 ****************************************************************/
9008
9009 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9010                                        struct spoolss_EnumPrintProcDataTypes *r)
9011 {
9012         WERROR result;
9013
9014         /* that's an [in out] buffer */
9015
9016         if (!r->in.buffer && (r->in.offered != 0)) {
9017                 return WERR_INVALID_PARAM;
9018         }
9019
9020         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9021
9022         *r->out.count = 0;
9023         *r->out.needed = 0;
9024         *r->out.info = NULL;
9025
9026         if (r->in.print_processor_name == NULL ||
9027             !strequal(r->in.print_processor_name, "winprint")) {
9028                 return WERR_UNKNOWN_PRINTPROCESSOR;
9029         }
9030
9031         switch (r->in.level) {
9032         case 1:
9033                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9034                                                         r->out.count);
9035                 break;
9036         default:
9037                 return WERR_UNKNOWN_LEVEL;
9038         }
9039
9040         if (!W_ERROR_IS_OK(result)) {
9041                 return result;
9042         }
9043
9044         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9045                                                      spoolss_EnumPrintProcDataTypes,
9046                                                      *r->out.info, r->in.level,
9047                                                      *r->out.count);
9048         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9049         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9050
9051         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9052 }
9053
9054 /****************************************************************************
9055  fill_monitor_1
9056 ****************************************************************************/
9057
9058 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9059                              struct spoolss_MonitorInfo1 *r,
9060                              const char *monitor_name)
9061 {
9062         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9063         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9064
9065         return WERR_OK;
9066 }
9067
9068 /****************************************************************************
9069  fill_monitor_2
9070 ****************************************************************************/
9071
9072 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9073                              struct spoolss_MonitorInfo2 *r,
9074                              const char *monitor_name,
9075                              const char *environment,
9076                              const char *dll_name)
9077 {
9078         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9079         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9080         r->environment                  = talloc_strdup(mem_ctx, environment);
9081         W_ERROR_HAVE_NO_MEMORY(r->environment);
9082         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9083         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9084
9085         return WERR_OK;
9086 }
9087
9088 /****************************************************************************
9089  enumprintmonitors level 1.
9090 ****************************************************************************/
9091
9092 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9093                                         union spoolss_MonitorInfo **info_p,
9094                                         uint32_t *count)
9095 {
9096         union spoolss_MonitorInfo *info;
9097         WERROR result = WERR_OK;
9098
9099         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9100         W_ERROR_HAVE_NO_MEMORY(info);
9101
9102         *count = 2;
9103
9104         result = fill_monitor_1(info, &info[0].info1,
9105                                 SPL_LOCAL_PORT);
9106         if (!W_ERROR_IS_OK(result)) {
9107                 goto out;
9108         }
9109
9110         result = fill_monitor_1(info, &info[1].info1,
9111                                 SPL_TCPIP_PORT);
9112         if (!W_ERROR_IS_OK(result)) {
9113                 goto out;
9114         }
9115
9116 out:
9117         if (!W_ERROR_IS_OK(result)) {
9118                 TALLOC_FREE(info);
9119                 *count = 0;
9120                 return result;
9121         }
9122
9123         *info_p = info;
9124
9125         return WERR_OK;
9126 }
9127
9128 /****************************************************************************
9129  enumprintmonitors level 2.
9130 ****************************************************************************/
9131
9132 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9133                                         union spoolss_MonitorInfo **info_p,
9134                                         uint32_t *count)
9135 {
9136         union spoolss_MonitorInfo *info;
9137         WERROR result = WERR_OK;
9138
9139         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9140         W_ERROR_HAVE_NO_MEMORY(info);
9141
9142         *count = 2;
9143
9144         result = fill_monitor_2(info, &info[0].info2,
9145                                 SPL_LOCAL_PORT,
9146                                 "Windows NT X86", /* FIXME */
9147                                 "localmon.dll");
9148         if (!W_ERROR_IS_OK(result)) {
9149                 goto out;
9150         }
9151
9152         result = fill_monitor_2(info, &info[1].info2,
9153                                 SPL_TCPIP_PORT,
9154                                 "Windows NT X86", /* FIXME */
9155                                 "tcpmon.dll");
9156         if (!W_ERROR_IS_OK(result)) {
9157                 goto out;
9158         }
9159
9160 out:
9161         if (!W_ERROR_IS_OK(result)) {
9162                 TALLOC_FREE(info);
9163                 *count = 0;
9164                 return result;
9165         }
9166
9167         *info_p = info;
9168
9169         return WERR_OK;
9170 }
9171
9172 /****************************************************************
9173  _spoolss_EnumMonitors
9174 ****************************************************************/
9175
9176 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9177                              struct spoolss_EnumMonitors *r)
9178 {
9179         WERROR result;
9180
9181         /* that's an [in out] buffer */
9182
9183         if (!r->in.buffer && (r->in.offered != 0)) {
9184                 return WERR_INVALID_PARAM;
9185         }
9186
9187         DEBUG(5,("_spoolss_EnumMonitors\n"));
9188
9189         /*
9190          * Enumerate the print monitors ...
9191          *
9192          * Just reply with "Local Port", to keep NT happy
9193          * and I can use my nice printer checker.
9194          */
9195
9196         *r->out.count = 0;
9197         *r->out.needed = 0;
9198         *r->out.info = NULL;
9199
9200         switch (r->in.level) {
9201         case 1:
9202                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9203                                                    r->out.count);
9204                 break;
9205         case 2:
9206                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9207                                                    r->out.count);
9208                 break;
9209         default:
9210                 return WERR_UNKNOWN_LEVEL;
9211         }
9212
9213         if (!W_ERROR_IS_OK(result)) {
9214                 return result;
9215         }
9216
9217         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9218                                                      spoolss_EnumMonitors,
9219                                                      *r->out.info, r->in.level,
9220                                                      *r->out.count);
9221         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9222         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9223
9224         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9225 }
9226
9227 /****************************************************************************
9228 ****************************************************************************/
9229
9230 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9231                              const print_queue_struct *queue,
9232                              int count, int snum,
9233                              struct spoolss_PrinterInfo2 *pinfo2,
9234                              uint32_t jobid,
9235                              struct spoolss_JobInfo1 *r)
9236 {
9237         int i = 0;
9238         bool found = false;
9239
9240         for (i=0; i<count; i++) {
9241                 if (queue[i].sysjob == (int)jobid) {
9242                         found = true;
9243                         break;
9244                 }
9245         }
9246
9247         if (found == false) {
9248                 /* NT treats not found as bad param... yet another bad choice */
9249                 return WERR_INVALID_PARAM;
9250         }
9251
9252         return fill_job_info1(mem_ctx,
9253                               r,
9254                               &queue[i],
9255                               i,
9256                               snum,
9257                               pinfo2);
9258 }
9259
9260 /****************************************************************************
9261 ****************************************************************************/
9262
9263 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9264                              const print_queue_struct *queue,
9265                              int count, int snum,
9266                              struct spoolss_PrinterInfo2 *pinfo2,
9267                              uint32_t jobid,
9268                              struct spoolss_JobInfo2 *r)
9269 {
9270         int i = 0;
9271         bool found = false;
9272         struct spoolss_DeviceMode *devmode;
9273         WERROR result;
9274
9275         for (i=0; i<count; i++) {
9276                 if (queue[i].sysjob == (int)jobid) {
9277                         found = true;
9278                         break;
9279                 }
9280         }
9281
9282         if (found == false) {
9283                 /* NT treats not found as bad param... yet another bad
9284                    choice */
9285                 return WERR_INVALID_PARAM;
9286         }
9287
9288         /*
9289          * if the print job does not have a DEVMODE associated with it,
9290          * just use the one for the printer. A NULL devicemode is not
9291          *  a failure condition
9292          */
9293
9294         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9295         if (!devmode) {
9296                 result = spoolss_create_default_devmode(mem_ctx,
9297                                                 pinfo2->printername,
9298                                                 &devmode);
9299                 if (!W_ERROR_IS_OK(result)) {
9300                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9301                         return result;
9302                 }
9303         }
9304
9305         return fill_job_info2(mem_ctx,
9306                               r,
9307                               &queue[i],
9308                               i,
9309                               snum,
9310                               pinfo2,
9311                               devmode);
9312 }
9313
9314 /****************************************************************
9315  _spoolss_GetJob
9316 ****************************************************************/
9317
9318 WERROR _spoolss_GetJob(struct pipes_struct *p,
9319                        struct spoolss_GetJob *r)
9320 {
9321         WERROR result = WERR_OK;
9322         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9323         int snum;
9324         int count;
9325         print_queue_struct      *queue = NULL;
9326         print_status_struct prt_status;
9327
9328         /* that's an [in out] buffer */
9329
9330         if (!r->in.buffer && (r->in.offered != 0)) {
9331                 return WERR_INVALID_PARAM;
9332         }
9333
9334         DEBUG(5,("_spoolss_GetJob\n"));
9335
9336         *r->out.needed = 0;
9337
9338         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9339                 return WERR_BADFID;
9340         }
9341
9342         result = winreg_get_printer_internal(p->mem_ctx,
9343                                     get_session_info_system(),
9344                                     p->msg_ctx,
9345                                     lp_const_servicename(snum),
9346                                     &pinfo2);
9347         if (!W_ERROR_IS_OK(result)) {
9348                 return result;
9349         }
9350
9351         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9352
9353         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9354                      count, prt_status.status, prt_status.message));
9355
9356         switch (r->in.level) {
9357         case 1:
9358                 result = getjob_level_1(p->mem_ctx,
9359                                         queue, count, snum, pinfo2,
9360                                         r->in.job_id, &r->out.info->info1);
9361                 break;
9362         case 2:
9363                 result = getjob_level_2(p->mem_ctx,
9364                                         queue, count, snum, pinfo2,
9365                                         r->in.job_id, &r->out.info->info2);
9366                 break;
9367         default:
9368                 result = WERR_UNKNOWN_LEVEL;
9369                 break;
9370         }
9371
9372         SAFE_FREE(queue);
9373         TALLOC_FREE(pinfo2);
9374
9375         if (!W_ERROR_IS_OK(result)) {
9376                 TALLOC_FREE(r->out.info);
9377                 return result;
9378         }
9379
9380         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9381                                                                                    r->in.level);
9382         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9383
9384         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9385 }
9386
9387 /****************************************************************
9388  _spoolss_GetPrinterDataEx
9389 ****************************************************************/
9390
9391 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9392                                  struct spoolss_GetPrinterDataEx *r)
9393 {
9394
9395         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9396         const char *printer;
9397         int                     snum = 0;
9398         WERROR result = WERR_OK;
9399         DATA_BLOB blob;
9400         enum winreg_Type val_type = REG_NONE;
9401         uint8_t *val_data = NULL;
9402         uint32_t val_size = 0;
9403         struct dcerpc_binding_handle *b;
9404         TALLOC_CTX *tmp_ctx;
9405
9406         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9407
9408         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9409                 r->in.key_name, r->in.value_name));
9410
9411         /* in case of problem, return some default values */
9412
9413         *r->out.needed  = 0;
9414         *r->out.type    = REG_NONE;
9415
9416         tmp_ctx = talloc_new(p->mem_ctx);
9417         if (!tmp_ctx) {
9418                 return WERR_NOMEM;
9419         }
9420
9421         if (!Printer) {
9422                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9423                         OUR_HANDLE(r->in.handle)));
9424                 result = WERR_BADFID;
9425                 goto done;
9426         }
9427
9428         /* check to see if the keyname is valid */
9429         if (!strlen(r->in.key_name)) {
9430                 result = WERR_INVALID_PARAM;
9431                 goto done;
9432         }
9433
9434         /* Is the handle to a printer or to the server? */
9435
9436         if (Printer->printer_type == SPLHND_SERVER) {
9437
9438                 union spoolss_PrinterData data;
9439
9440                 result = getprinterdata_printer_server(tmp_ctx,
9441                                                        r->in.value_name,
9442                                                        r->out.type,
9443                                                        &data);
9444                 if (!W_ERROR_IS_OK(result)) {
9445                         goto done;
9446                 }
9447
9448                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9449                                                   *r->out.type, &data);
9450                 if (!W_ERROR_IS_OK(result)) {
9451                         goto done;
9452                 }
9453
9454                 *r->out.needed = blob.length;
9455
9456                 if (r->in.offered >= *r->out.needed) {
9457                         memcpy(r->out.data, blob.data, blob.length);
9458                 }
9459
9460                 result = WERR_OK;
9461                 goto done;
9462         }
9463
9464         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9465                 result = WERR_BADFID;
9466                 goto done;
9467         }
9468         printer = lp_const_servicename(snum);
9469
9470         result = winreg_printer_binding_handle(tmp_ctx,
9471                                                get_session_info_system(),
9472                                                p->msg_ctx,
9473                                                &b);
9474         if (!W_ERROR_IS_OK(result)) {
9475                 goto done;
9476         }
9477
9478         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9479         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9480             strequal(r->in.value_name, "ChangeId")) {
9481                 *r->out.type = REG_DWORD;
9482                 *r->out.needed = 4;
9483                 if (r->in.offered >= *r->out.needed) {
9484                         uint32_t changeid = 0;
9485
9486                         result = winreg_printer_get_changeid(tmp_ctx, b,
9487                                                              printer,
9488                                                              &changeid);
9489                         if (!W_ERROR_IS_OK(result)) {
9490                                 goto done;
9491                         }
9492
9493                         SIVAL(r->out.data, 0, changeid);
9494                         result = WERR_OK;
9495                 }
9496                 goto done;
9497         }
9498
9499         result = winreg_get_printer_dataex(tmp_ctx, b,
9500                                            printer,
9501                                            r->in.key_name,
9502                                            r->in.value_name,
9503                                            &val_type,
9504                                            &val_data,
9505                                            &val_size);
9506         if (!W_ERROR_IS_OK(result)) {
9507                 goto done;
9508         }
9509
9510         *r->out.needed = val_size;
9511         *r->out.type = val_type;
9512
9513         if (r->in.offered >= *r->out.needed) {
9514                 memcpy(r->out.data, val_data, val_size);
9515         }
9516
9517 done:
9518         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9519
9520         if (W_ERROR_IS_OK(result)) {
9521                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9522         }
9523
9524         talloc_free(tmp_ctx);
9525         return result;
9526 }
9527
9528 /****************************************************************
9529  _spoolss_SetPrinterDataEx
9530 ****************************************************************/
9531
9532 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9533                                  struct spoolss_SetPrinterDataEx *r)
9534 {
9535         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9536         int                     snum = 0;
9537         WERROR                  result = WERR_OK;
9538         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9539         char                    *oid_string;
9540         struct dcerpc_binding_handle *b;
9541         TALLOC_CTX *tmp_ctx;
9542
9543         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9544
9545         /* From MSDN documentation of SetPrinterDataEx: pass request to
9546            SetPrinterData if key is "PrinterDriverData" */
9547
9548         if (!Printer) {
9549                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9550                         OUR_HANDLE(r->in.handle)));
9551                 return WERR_BADFID;
9552         }
9553
9554         if (Printer->printer_type == SPLHND_SERVER) {
9555                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9556                         "Not implemented for server handles yet\n"));
9557                 return WERR_INVALID_PARAM;
9558         }
9559
9560         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9561                 return WERR_BADFID;
9562         }
9563
9564         /*
9565          * Access check : NT returns "access denied" if you make a
9566          * SetPrinterData call without the necessary privildge.
9567          * we were originally returning OK if nothing changed
9568          * which made Win2k issue **a lot** of SetPrinterData
9569          * when connecting to a printer  --jerry
9570          */
9571
9572         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9573                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9574                         "change denied by handle access permissions\n"));
9575                 return WERR_ACCESS_DENIED;
9576         }
9577
9578         tmp_ctx = talloc_new(p->mem_ctx);
9579         if (!tmp_ctx) {
9580                 return WERR_NOMEM;
9581         }
9582
9583         result = winreg_printer_binding_handle(tmp_ctx,
9584                                                get_session_info_system(),
9585                                                p->msg_ctx,
9586                                                &b);
9587         if (!W_ERROR_IS_OK(result)) {
9588                 goto done;
9589         }
9590
9591         result = winreg_get_printer(tmp_ctx, b,
9592                                     lp_servicename(talloc_tos(), snum),
9593                                     &pinfo2);
9594         if (!W_ERROR_IS_OK(result)) {
9595                 goto done;
9596         }
9597
9598         /* check for OID in valuename */
9599
9600         oid_string = strchr(r->in.value_name, ',');
9601         if (oid_string) {
9602                 *oid_string = '\0';
9603                 oid_string++;
9604         }
9605
9606         /* save the registry data */
9607
9608         result = winreg_set_printer_dataex(tmp_ctx, b,
9609                                            pinfo2->sharename,
9610                                            r->in.key_name,
9611                                            r->in.value_name,
9612                                            r->in.type,
9613                                            r->in.data,
9614                                            r->in.offered);
9615
9616         if (W_ERROR_IS_OK(result)) {
9617                 /* save the OID if one was specified */
9618                 if (oid_string) {
9619                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9620                                 r->in.key_name, SPOOL_OID_KEY);
9621                         if (!str) {
9622                                 result = WERR_NOMEM;
9623                                 goto done;
9624                         }
9625
9626                         /*
9627                          * I'm not checking the status here on purpose.  Don't know
9628                          * if this is right, but I'm returning the status from the
9629                          * previous set_printer_dataex() call.  I have no idea if
9630                          * this is right.    --jerry
9631                          */
9632                         winreg_set_printer_dataex(tmp_ctx, b,
9633                                                   pinfo2->sharename,
9634                                                   str,
9635                                                   r->in.value_name,
9636                                                   REG_SZ,
9637                                                   (uint8_t *) oid_string,
9638                                                   strlen(oid_string) + 1);
9639                 }
9640
9641                 result = winreg_printer_update_changeid(tmp_ctx, b,
9642                                                         lp_const_servicename(snum));
9643
9644         }
9645
9646 done:
9647         talloc_free(tmp_ctx);
9648         return result;
9649 }
9650
9651 /****************************************************************
9652  _spoolss_DeletePrinterDataEx
9653 ****************************************************************/
9654
9655 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9656                                     struct spoolss_DeletePrinterDataEx *r)
9657 {
9658         const char *printer;
9659         int             snum=0;
9660         WERROR          status = WERR_OK;
9661         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9662
9663         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9664
9665         if (!Printer) {
9666                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9667                         "Invalid handle (%s:%u:%u).\n",
9668                         OUR_HANDLE(r->in.handle)));
9669                 return WERR_BADFID;
9670         }
9671
9672         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9673                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9674                         "printer properties change denied by handle\n"));
9675                 return WERR_ACCESS_DENIED;
9676         }
9677
9678         if (!r->in.value_name || !r->in.key_name) {
9679                 return WERR_NOMEM;
9680         }
9681
9682         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9683                 return WERR_BADFID;
9684         }
9685         printer = lp_const_servicename(snum);
9686
9687         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9688                                               get_session_info_system(),
9689                                               p->msg_ctx,
9690                                               printer,
9691                                               r->in.key_name,
9692                                               r->in.value_name);
9693         if (W_ERROR_IS_OK(status)) {
9694                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9695                                                         get_session_info_system(),
9696                                                         p->msg_ctx,
9697                                                         printer);
9698         }
9699
9700         return status;
9701 }
9702
9703 /****************************************************************
9704  _spoolss_EnumPrinterKey
9705 ****************************************************************/
9706
9707 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9708                                struct spoolss_EnumPrinterKey *r)
9709 {
9710         uint32_t        num_keys;
9711         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9712         int             snum = 0;
9713         WERROR          result = WERR_BADFILE;
9714         const char **array = NULL;
9715         DATA_BLOB blob;
9716
9717         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9718
9719         if (!Printer) {
9720                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9721                         OUR_HANDLE(r->in.handle)));
9722                 return WERR_BADFID;
9723         }
9724
9725         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9726                 return WERR_BADFID;
9727         }
9728
9729         result = winreg_enum_printer_key_internal(p->mem_ctx,
9730                                          get_session_info_system(),
9731                                          p->msg_ctx,
9732                                          lp_const_servicename(snum),
9733                                          r->in.key_name,
9734                                          &num_keys,
9735                                          &array);
9736         if (!W_ERROR_IS_OK(result)) {
9737                 goto done;
9738         }
9739
9740         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9741                 result = WERR_NOMEM;
9742                 goto done;
9743         }
9744
9745         *r->out._ndr_size = r->in.offered / 2;
9746         *r->out.needed = blob.length;
9747
9748         if (r->in.offered < *r->out.needed) {
9749                 result = WERR_MORE_DATA;
9750         } else {
9751                 result = WERR_OK;
9752                 r->out.key_buffer->string_array = array;
9753         }
9754
9755  done:
9756         if (!W_ERROR_IS_OK(result)) {
9757                 TALLOC_FREE(array);
9758                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9759                         *r->out.needed = 0;
9760                 }
9761         }
9762
9763         return result;
9764 }
9765
9766 /****************************************************************
9767  _spoolss_DeletePrinterKey
9768 ****************************************************************/
9769
9770 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9771                                  struct spoolss_DeletePrinterKey *r)
9772 {
9773         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9774         int                     snum=0;
9775         WERROR                  status;
9776         const char *printer;
9777         struct dcerpc_binding_handle *b;
9778         TALLOC_CTX *tmp_ctx;
9779
9780         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9781
9782         if (!Printer) {
9783                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9784                         OUR_HANDLE(r->in.handle)));
9785                 return WERR_BADFID;
9786         }
9787
9788         /* if keyname == NULL, return error */
9789         if ( !r->in.key_name )
9790                 return WERR_INVALID_PARAM;
9791
9792         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9793                 return WERR_BADFID;
9794         }
9795
9796         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9797                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9798                         "printer properties change denied by handle\n"));
9799                 return WERR_ACCESS_DENIED;
9800         }
9801
9802         printer = lp_const_servicename(snum);
9803
9804         tmp_ctx = talloc_new(p->mem_ctx);
9805         if (!tmp_ctx) {
9806                 return WERR_NOMEM;
9807         }
9808
9809         status = winreg_printer_binding_handle(tmp_ctx,
9810                                                get_session_info_system(),
9811                                                p->msg_ctx,
9812                                                &b);
9813         if (!W_ERROR_IS_OK(status)) {
9814                 goto done;
9815         }
9816
9817         /* delete the key and all subkeys */
9818         status = winreg_delete_printer_key(tmp_ctx, b,
9819                                            printer,
9820                                            r->in.key_name);
9821         if (W_ERROR_IS_OK(status)) {
9822                 status = winreg_printer_update_changeid(tmp_ctx, b,
9823                                                         printer);
9824         }
9825
9826 done:
9827         talloc_free(tmp_ctx);
9828         return status;
9829 }
9830
9831 /****************************************************************
9832  _spoolss_EnumPrinterDataEx
9833 ****************************************************************/
9834
9835 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9836                                   struct spoolss_EnumPrinterDataEx *r)
9837 {
9838         uint32_t        count = 0;
9839         struct spoolss_PrinterEnumValues *info = NULL;
9840         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9841         int             snum;
9842         WERROR          result;
9843
9844         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9845
9846         *r->out.count = 0;
9847         *r->out.needed = 0;
9848         *r->out.info = NULL;
9849
9850         if (!Printer) {
9851                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9852                         OUR_HANDLE(r->in.handle)));
9853                 return WERR_BADFID;
9854         }
9855
9856         /*
9857          * first check for a keyname of NULL or "".  Win2k seems to send
9858          * this a lot and we should send back WERR_INVALID_PARAM
9859          * no need to spend time looking up the printer in this case.
9860          * --jerry
9861          */
9862
9863         if (!strlen(r->in.key_name)) {
9864                 result = WERR_INVALID_PARAM;
9865                 goto done;
9866         }
9867
9868         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9869                 return WERR_BADFID;
9870         }
9871
9872         /* now look for a match on the key name */
9873         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9874                                             get_session_info_system(),
9875                                             p->msg_ctx,
9876                                             lp_const_servicename(snum),
9877                                             r->in.key_name,
9878                                             &count,
9879                                             &info);
9880         if (!W_ERROR_IS_OK(result)) {
9881                 goto done;
9882         }
9883
9884 #if 0 /* FIXME - gd */
9885         /* housekeeping information in the reply */
9886
9887         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9888          * the hand marshalled container size is a multiple
9889          * of 4 bytes for RPC alignment.
9890          */
9891
9892         if (needed % 4) {
9893                 needed += 4-(needed % 4);
9894         }
9895 #endif
9896         *r->out.count   = count;
9897         *r->out.info    = info;
9898
9899  done:
9900         if (!W_ERROR_IS_OK(result)) {
9901                 return result;
9902         }
9903
9904         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9905                                                spoolss_EnumPrinterDataEx,
9906                                                *r->out.info,
9907                                                *r->out.count);
9908         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9909         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9910
9911         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9912 }
9913
9914 /****************************************************************************
9915 ****************************************************************************/
9916
9917 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9918                                                  const char *servername,
9919                                                  const char *environment,
9920                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9921 {
9922         WERROR werr;
9923         char *path = NULL;
9924
9925         werr = compose_spoolss_server_path(mem_ctx,
9926                                            servername,
9927                                            environment,
9928                                            SPOOLSS_PRTPROCS_PATH,
9929                                            &path);
9930         if (!W_ERROR_IS_OK(werr)) {
9931                 return werr;
9932         }
9933
9934         DEBUG(4,("print processor directory: [%s]\n", path));
9935
9936         r->directory_name = path;
9937
9938         return WERR_OK;
9939 }
9940
9941 /****************************************************************
9942  _spoolss_GetPrintProcessorDirectory
9943 ****************************************************************/
9944
9945 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9946                                            struct spoolss_GetPrintProcessorDirectory *r)
9947 {
9948         WERROR result;
9949         char *prnproc_share = NULL;
9950         bool prnproc_share_exists = false;
9951         int snum;
9952
9953         /* that's an [in out] buffer */
9954
9955         if (!r->in.buffer && (r->in.offered != 0)) {
9956                 return WERR_INVALID_PARAM;
9957         }
9958
9959         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9960                 r->in.level));
9961
9962         *r->out.needed = 0;
9963
9964         /* r->in.level is ignored */
9965
9966         /* We always should reply with a local print processor directory so that
9967          * users are not forced to have a [prnproc$] share on the Samba spoolss
9968          * server, if users decide to do so, lets announce it though - Guenther */
9969
9970         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9971         if (!prnproc_share) {
9972                 return WERR_NOMEM;
9973         }
9974         if (snum != -1) {
9975                 prnproc_share_exists = true;
9976         }
9977
9978         result = getprintprocessordirectory_level_1(p->mem_ctx,
9979                                                     prnproc_share_exists ? r->in.server : NULL,
9980                                                     r->in.environment,
9981                                                     &r->out.info->info1);
9982         if (!W_ERROR_IS_OK(result)) {
9983                 TALLOC_FREE(r->out.info);
9984                 return result;
9985         }
9986
9987         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9988                                                                                    r->out.info, r->in.level);
9989         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9990
9991         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9992 }
9993
9994 /*******************************************************************
9995  ********************************************************************/
9996
9997 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9998                                const char *dllname)
9999 {
10000         enum ndr_err_code ndr_err;
10001         struct spoolss_MonitorUi ui;
10002
10003         ui.dll_name = dllname;
10004
10005         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10006                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10007         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10008                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10009         }
10010         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10011 }
10012
10013 /*******************************************************************
10014  Streams the monitor UI DLL name in UNICODE
10015 *******************************************************************/
10016
10017 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10018                                struct security_token *token, DATA_BLOB *in,
10019                                DATA_BLOB *out, uint32_t *needed)
10020 {
10021         const char *dllname = "tcpmonui.dll";
10022
10023         *needed = (strlen(dllname)+1) * 2;
10024
10025         if (out->length < *needed) {
10026                 return WERR_INSUFFICIENT_BUFFER;
10027         }
10028
10029         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10030                 return WERR_NOMEM;
10031         }
10032
10033         return WERR_OK;
10034 }
10035
10036 /*******************************************************************
10037  ********************************************************************/
10038
10039 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10040                              struct spoolss_PortData1 *port1,
10041                              const DATA_BLOB *buf)
10042 {
10043         enum ndr_err_code ndr_err;
10044         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10045                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10046         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10047                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10048         }
10049         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10050 }
10051
10052 /*******************************************************************
10053  ********************************************************************/
10054
10055 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10056                              struct spoolss_PortData2 *port2,
10057                              const DATA_BLOB *buf)
10058 {
10059         enum ndr_err_code ndr_err;
10060         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10061                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10062         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10063                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10064         }
10065         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10066 }
10067
10068 /*******************************************************************
10069  Create a new TCP/IP port
10070 *******************************************************************/
10071
10072 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10073                              struct security_token *token, DATA_BLOB *in,
10074                              DATA_BLOB *out, uint32_t *needed)
10075 {
10076         struct spoolss_PortData1 port1;
10077         struct spoolss_PortData2 port2;
10078         char *device_uri = NULL;
10079         uint32_t version;
10080
10081         const char *portname;
10082         const char *hostaddress;
10083         const char *queue;
10084         uint32_t port_number;
10085         uint32_t protocol;
10086
10087         /* peek for spoolss_PortData version */
10088
10089         if (!in || (in->length < (128 + 4))) {
10090                 return WERR_GENERAL_FAILURE;
10091         }
10092
10093         version = IVAL(in->data, 128);
10094
10095         switch (version) {
10096                 case 1:
10097                         ZERO_STRUCT(port1);
10098
10099                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10100                                 return WERR_NOMEM;
10101                         }
10102
10103                         portname        = port1.portname;
10104                         hostaddress     = port1.hostaddress;
10105                         queue           = port1.queue;
10106                         protocol        = port1.protocol;
10107                         port_number     = port1.port_number;
10108
10109                         break;
10110                 case 2:
10111                         ZERO_STRUCT(port2);
10112
10113                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10114                                 return WERR_NOMEM;
10115                         }
10116
10117                         portname        = port2.portname;
10118                         hostaddress     = port2.hostaddress;
10119                         queue           = port2.queue;
10120                         protocol        = port2.protocol;
10121                         port_number     = port2.port_number;
10122
10123                         break;
10124                 default:
10125                         DEBUG(1,("xcvtcp_addport: "
10126                                 "unknown version of port_data: %d\n", version));
10127                         return WERR_UNKNOWN_PORT;
10128         }
10129
10130         /* create the device URI and call the add_port_hook() */
10131
10132         switch (protocol) {
10133         case PROTOCOL_RAWTCP_TYPE:
10134                 device_uri = talloc_asprintf(mem_ctx,
10135                                 "socket://%s:%d/", hostaddress,
10136                                 port_number);
10137                 break;
10138
10139         case PROTOCOL_LPR_TYPE:
10140                 device_uri = talloc_asprintf(mem_ctx,
10141                         "lpr://%s/%s", hostaddress, queue );
10142                 break;
10143
10144         default:
10145                 return WERR_UNKNOWN_PORT;
10146         }
10147
10148         if (!device_uri) {
10149                 return WERR_NOMEM;
10150         }
10151
10152         return add_port_hook(mem_ctx, token, portname, device_uri);
10153 }
10154
10155 /*******************************************************************
10156 *******************************************************************/
10157
10158 struct xcv_api_table xcvtcp_cmds[] = {
10159         { "MonitorUI",  xcvtcp_monitorui },
10160         { "AddPort",    xcvtcp_addport},
10161         { NULL,         NULL }
10162 };
10163
10164 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10165                                      struct security_token *token, const char *command,
10166                                      DATA_BLOB *inbuf,
10167                                      DATA_BLOB *outbuf,
10168                                      uint32_t *needed )
10169 {
10170         int i;
10171
10172         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10173
10174         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10175                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10176                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10177         }
10178
10179         return WERR_BADFUNC;
10180 }
10181
10182 /*******************************************************************
10183 *******************************************************************/
10184 #if 0   /* don't support management using the "Local Port" monitor */
10185
10186 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10187                                  struct security_token *token, DATA_BLOB *in,
10188                                  DATA_BLOB *out, uint32_t *needed)
10189 {
10190         const char *dllname = "localui.dll";
10191
10192         *needed = (strlen(dllname)+1) * 2;
10193
10194         if (out->length < *needed) {
10195                 return WERR_INSUFFICIENT_BUFFER;
10196         }
10197
10198         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10199                 return WERR_NOMEM;
10200         }
10201
10202         return WERR_OK;
10203 }
10204
10205 /*******************************************************************
10206 *******************************************************************/
10207
10208 struct xcv_api_table xcvlocal_cmds[] = {
10209         { "MonitorUI",  xcvlocal_monitorui },
10210         { NULL,         NULL }
10211 };
10212 #else
10213 struct xcv_api_table xcvlocal_cmds[] = {
10214         { NULL,         NULL }
10215 };
10216 #endif
10217
10218
10219
10220 /*******************************************************************
10221 *******************************************************************/
10222
10223 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10224                                        struct security_token *token, const char *command,
10225                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10226                                        uint32_t *needed)
10227 {
10228         int i;
10229
10230         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10231
10232         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10233                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10234                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10235         }
10236         return WERR_BADFUNC;
10237 }
10238
10239 /****************************************************************
10240  _spoolss_XcvData
10241 ****************************************************************/
10242
10243 WERROR _spoolss_XcvData(struct pipes_struct *p,
10244                         struct spoolss_XcvData *r)
10245 {
10246         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10247         DATA_BLOB out_data = data_blob_null;
10248         WERROR werror;
10249
10250         if (!Printer) {
10251                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10252                         OUR_HANDLE(r->in.handle)));
10253                 return WERR_BADFID;
10254         }
10255
10256         /* Has to be a handle to the TCP/IP port monitor */
10257
10258         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10259                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10260                 return WERR_BADFID;
10261         }
10262
10263         /* requires administrative access to the server */
10264
10265         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10266                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10267                 return WERR_ACCESS_DENIED;
10268         }
10269
10270         /* Allocate the outgoing buffer */
10271
10272         if (r->in.out_data_size) {
10273                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10274                 if (out_data.data == NULL) {
10275                         return WERR_NOMEM;
10276                 }
10277         }
10278
10279         switch ( Printer->printer_type ) {
10280         case SPLHND_PORTMON_TCP:
10281                 werror = process_xcvtcp_command(p->mem_ctx,
10282                                                 p->session_info->security_token,
10283                                                 r->in.function_name,
10284                                                 &r->in.in_data, &out_data,
10285                                                 r->out.needed);
10286                 break;
10287         case SPLHND_PORTMON_LOCAL:
10288                 werror = process_xcvlocal_command(p->mem_ctx,
10289                                                   p->session_info->security_token,
10290                                                   r->in.function_name,
10291                                                   &r->in.in_data, &out_data,
10292                                                   r->out.needed);
10293                 break;
10294         default:
10295                 werror = WERR_INVALID_PRINT_MONITOR;
10296         }
10297
10298         if (!W_ERROR_IS_OK(werror)) {
10299                 return werror;
10300         }
10301
10302         *r->out.status_code = 0;
10303
10304         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10305                 memcpy(r->out.out_data, out_data.data,
10306                         MIN(r->in.out_data_size, out_data.length));
10307         }
10308
10309         return WERR_OK;
10310 }
10311
10312 /****************************************************************
10313  _spoolss_AddPrintProcessor
10314 ****************************************************************/
10315
10316 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10317                                   struct spoolss_AddPrintProcessor *r)
10318 {
10319         /* for now, just indicate success and ignore the add.  We'll
10320            automatically set the winprint processor for printer
10321            entries later.  Used to debug the LexMark Optra S 1855 PCL
10322            driver --jerry */
10323
10324         return WERR_OK;
10325 }
10326
10327 /****************************************************************
10328  _spoolss_AddPort
10329 ****************************************************************/
10330
10331 WERROR _spoolss_AddPort(struct pipes_struct *p,
10332                         struct spoolss_AddPort *r)
10333 {
10334         /* do what w2k3 does */
10335
10336         return WERR_NOT_SUPPORTED;
10337 }
10338
10339 /****************************************************************
10340  _spoolss_GetPrinterDriver
10341 ****************************************************************/
10342
10343 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10344                                  struct spoolss_GetPrinterDriver *r)
10345 {
10346         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10347         return WERR_NOT_SUPPORTED;
10348 }
10349
10350 /****************************************************************
10351  _spoolss_ReadPrinter
10352 ****************************************************************/
10353
10354 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10355                             struct spoolss_ReadPrinter *r)
10356 {
10357         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10358         return WERR_NOT_SUPPORTED;
10359 }
10360
10361 /****************************************************************
10362  _spoolss_WaitForPrinterChange
10363 ****************************************************************/
10364
10365 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10366                                      struct spoolss_WaitForPrinterChange *r)
10367 {
10368         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10369         return WERR_NOT_SUPPORTED;
10370 }
10371
10372 /****************************************************************
10373  _spoolss_ConfigurePort
10374 ****************************************************************/
10375
10376 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10377                               struct spoolss_ConfigurePort *r)
10378 {
10379         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10380         return WERR_NOT_SUPPORTED;
10381 }
10382
10383 /****************************************************************
10384  _spoolss_DeletePort
10385 ****************************************************************/
10386
10387 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10388                            struct spoolss_DeletePort *r)
10389 {
10390         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10391         return WERR_NOT_SUPPORTED;
10392 }
10393
10394 /****************************************************************
10395  _spoolss_CreatePrinterIC
10396 ****************************************************************/
10397
10398 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10399                                 struct spoolss_CreatePrinterIC *r)
10400 {
10401         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10402         return WERR_NOT_SUPPORTED;
10403 }
10404
10405 /****************************************************************
10406  _spoolss_PlayGDIScriptOnPrinterIC
10407 ****************************************************************/
10408
10409 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10410                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10411 {
10412         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10413         return WERR_NOT_SUPPORTED;
10414 }
10415
10416 /****************************************************************
10417  _spoolss_DeletePrinterIC
10418 ****************************************************************/
10419
10420 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10421                                 struct spoolss_DeletePrinterIC *r)
10422 {
10423         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10424         return WERR_NOT_SUPPORTED;
10425 }
10426
10427 /****************************************************************
10428  _spoolss_AddPrinterConnection
10429 ****************************************************************/
10430
10431 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10432                                      struct spoolss_AddPrinterConnection *r)
10433 {
10434         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10435         return WERR_NOT_SUPPORTED;
10436 }
10437
10438 /****************************************************************
10439  _spoolss_DeletePrinterConnection
10440 ****************************************************************/
10441
10442 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10443                                         struct spoolss_DeletePrinterConnection *r)
10444 {
10445         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10446         return WERR_NOT_SUPPORTED;
10447 }
10448
10449 /****************************************************************
10450  _spoolss_PrinterMessageBox
10451 ****************************************************************/
10452
10453 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10454                                   struct spoolss_PrinterMessageBox *r)
10455 {
10456         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10457         return WERR_NOT_SUPPORTED;
10458 }
10459
10460 /****************************************************************
10461  _spoolss_AddMonitor
10462 ****************************************************************/
10463
10464 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10465                            struct spoolss_AddMonitor *r)
10466 {
10467         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10468         return WERR_NOT_SUPPORTED;
10469 }
10470
10471 /****************************************************************
10472  _spoolss_DeleteMonitor
10473 ****************************************************************/
10474
10475 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10476                               struct spoolss_DeleteMonitor *r)
10477 {
10478         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10479         return WERR_NOT_SUPPORTED;
10480 }
10481
10482 /****************************************************************
10483  _spoolss_DeletePrintProcessor
10484 ****************************************************************/
10485
10486 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10487                                      struct spoolss_DeletePrintProcessor *r)
10488 {
10489         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10490         return WERR_NOT_SUPPORTED;
10491 }
10492
10493 /****************************************************************
10494  _spoolss_AddPrintProvidor
10495 ****************************************************************/
10496
10497 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10498                                  struct spoolss_AddPrintProvidor *r)
10499 {
10500         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10501         return WERR_NOT_SUPPORTED;
10502 }
10503
10504 /****************************************************************
10505  _spoolss_DeletePrintProvidor
10506 ****************************************************************/
10507
10508 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10509                                     struct spoolss_DeletePrintProvidor *r)
10510 {
10511         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10512         return WERR_NOT_SUPPORTED;
10513 }
10514
10515 /****************************************************************
10516  _spoolss_FindFirstPrinterChangeNotification
10517 ****************************************************************/
10518
10519 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10520                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10521 {
10522         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10523         return WERR_NOT_SUPPORTED;
10524 }
10525
10526 /****************************************************************
10527  _spoolss_FindNextPrinterChangeNotification
10528 ****************************************************************/
10529
10530 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10531                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10532 {
10533         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10534         return WERR_NOT_SUPPORTED;
10535 }
10536
10537 /****************************************************************
10538  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10539 ****************************************************************/
10540
10541 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10542                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10543 {
10544         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10545         return WERR_NOT_SUPPORTED;
10546 }
10547
10548 /****************************************************************
10549  _spoolss_ReplyOpenPrinter
10550 ****************************************************************/
10551
10552 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10553                                  struct spoolss_ReplyOpenPrinter *r)
10554 {
10555         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10556         return WERR_NOT_SUPPORTED;
10557 }
10558
10559 /****************************************************************
10560  _spoolss_RouterReplyPrinter
10561 ****************************************************************/
10562
10563 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10564                                    struct spoolss_RouterReplyPrinter *r)
10565 {
10566         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10567         return WERR_NOT_SUPPORTED;
10568 }
10569
10570 /****************************************************************
10571  _spoolss_ReplyClosePrinter
10572 ****************************************************************/
10573
10574 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10575                                   struct spoolss_ReplyClosePrinter *r)
10576 {
10577         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10578         return WERR_NOT_SUPPORTED;
10579 }
10580
10581 /****************************************************************
10582  _spoolss_AddPortEx
10583 ****************************************************************/
10584
10585 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10586                           struct spoolss_AddPortEx *r)
10587 {
10588         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10589         return WERR_NOT_SUPPORTED;
10590 }
10591
10592 /****************************************************************
10593  _spoolss_RouterFindFirstPrinterChangeNotification
10594 ****************************************************************/
10595
10596 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10597                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10598 {
10599         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10600         return WERR_NOT_SUPPORTED;
10601 }
10602
10603 /****************************************************************
10604  _spoolss_SpoolerInit
10605 ****************************************************************/
10606
10607 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10608                             struct spoolss_SpoolerInit *r)
10609 {
10610         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10611         return WERR_NOT_SUPPORTED;
10612 }
10613
10614 /****************************************************************
10615  _spoolss_ResetPrinterEx
10616 ****************************************************************/
10617
10618 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10619                                struct spoolss_ResetPrinterEx *r)
10620 {
10621         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10622         return WERR_NOT_SUPPORTED;
10623 }
10624
10625 /****************************************************************
10626  _spoolss_RouterReplyPrinterEx
10627 ****************************************************************/
10628
10629 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10630                                      struct spoolss_RouterReplyPrinterEx *r)
10631 {
10632         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10633         return WERR_NOT_SUPPORTED;
10634 }
10635
10636 /****************************************************************
10637  _spoolss_44
10638 ****************************************************************/
10639
10640 WERROR _spoolss_44(struct pipes_struct *p,
10641                    struct spoolss_44 *r)
10642 {
10643         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10644         return WERR_NOT_SUPPORTED;
10645 }
10646
10647 /****************************************************************
10648  _spoolss_SetPort
10649 ****************************************************************/
10650
10651 WERROR _spoolss_SetPort(struct pipes_struct *p,
10652                         struct spoolss_SetPort *r)
10653 {
10654         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10655         return WERR_NOT_SUPPORTED;
10656 }
10657
10658 /****************************************************************
10659  _spoolss_4a
10660 ****************************************************************/
10661
10662 WERROR _spoolss_4a(struct pipes_struct *p,
10663                    struct spoolss_4a *r)
10664 {
10665         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10666         return WERR_NOT_SUPPORTED;
10667 }
10668
10669 /****************************************************************
10670  _spoolss_4b
10671 ****************************************************************/
10672
10673 WERROR _spoolss_4b(struct pipes_struct *p,
10674                    struct spoolss_4b *r)
10675 {
10676         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10677         return WERR_NOT_SUPPORTED;
10678 }
10679
10680 /****************************************************************
10681  _spoolss_4c
10682 ****************************************************************/
10683
10684 WERROR _spoolss_4c(struct pipes_struct *p,
10685                    struct spoolss_4c *r)
10686 {
10687         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10688         return WERR_NOT_SUPPORTED;
10689 }
10690
10691 /****************************************************************
10692  _spoolss_53
10693 ****************************************************************/
10694
10695 WERROR _spoolss_53(struct pipes_struct *p,
10696                    struct spoolss_53 *r)
10697 {
10698         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10699         return WERR_NOT_SUPPORTED;
10700 }
10701
10702 /****************************************************************
10703  _spoolss_AddPerMachineConnection
10704 ****************************************************************/
10705
10706 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10707                                         struct spoolss_AddPerMachineConnection *r)
10708 {
10709         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10710         return WERR_NOT_SUPPORTED;
10711 }
10712
10713 /****************************************************************
10714  _spoolss_DeletePerMachineConnection
10715 ****************************************************************/
10716
10717 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10718                                            struct spoolss_DeletePerMachineConnection *r)
10719 {
10720         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10721         return WERR_NOT_SUPPORTED;
10722 }
10723
10724 /****************************************************************
10725  _spoolss_EnumPerMachineConnections
10726 ****************************************************************/
10727
10728 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10729                                           struct spoolss_EnumPerMachineConnections *r)
10730 {
10731         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10732         return WERR_NOT_SUPPORTED;
10733 }
10734
10735 /****************************************************************
10736  _spoolss_5a
10737 ****************************************************************/
10738
10739 WERROR _spoolss_5a(struct pipes_struct *p,
10740                    struct spoolss_5a *r)
10741 {
10742         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10743         return WERR_NOT_SUPPORTED;
10744 }
10745
10746 /****************************************************************
10747  _spoolss_5b
10748 ****************************************************************/
10749
10750 WERROR _spoolss_5b(struct pipes_struct *p,
10751                    struct spoolss_5b *r)
10752 {
10753         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10754         return WERR_NOT_SUPPORTED;
10755 }
10756
10757 /****************************************************************
10758  _spoolss_5c
10759 ****************************************************************/
10760
10761 WERROR _spoolss_5c(struct pipes_struct *p,
10762                    struct spoolss_5c *r)
10763 {
10764         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10765         return WERR_NOT_SUPPORTED;
10766 }
10767
10768 /****************************************************************
10769  _spoolss_5d
10770 ****************************************************************/
10771
10772 WERROR _spoolss_5d(struct pipes_struct *p,
10773                    struct spoolss_5d *r)
10774 {
10775         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10776         return WERR_NOT_SUPPORTED;
10777 }
10778
10779 /****************************************************************
10780  _spoolss_5e
10781 ****************************************************************/
10782
10783 WERROR _spoolss_5e(struct pipes_struct *p,
10784                    struct spoolss_5e *r)
10785 {
10786         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10787         return WERR_NOT_SUPPORTED;
10788 }
10789
10790 /****************************************************************
10791  _spoolss_5f
10792 ****************************************************************/
10793
10794 WERROR _spoolss_5f(struct pipes_struct *p,
10795                    struct spoolss_5f *r)
10796 {
10797         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10798         return WERR_NOT_SUPPORTED;
10799 }
10800
10801 /****************************************************************
10802  _spoolss_60
10803 ****************************************************************/
10804
10805 WERROR _spoolss_60(struct pipes_struct *p,
10806                    struct spoolss_60 *r)
10807 {
10808         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10809         return WERR_NOT_SUPPORTED;
10810 }
10811
10812 /****************************************************************
10813  _spoolss_61
10814 ****************************************************************/
10815
10816 WERROR _spoolss_61(struct pipes_struct *p,
10817                    struct spoolss_61 *r)
10818 {
10819         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10820         return WERR_NOT_SUPPORTED;
10821 }
10822
10823 /****************************************************************
10824  _spoolss_62
10825 ****************************************************************/
10826
10827 WERROR _spoolss_62(struct pipes_struct *p,
10828                    struct spoolss_62 *r)
10829 {
10830         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10831         return WERR_NOT_SUPPORTED;
10832 }
10833
10834 /****************************************************************
10835  _spoolss_63
10836 ****************************************************************/
10837
10838 WERROR _spoolss_63(struct pipes_struct *p,
10839                    struct spoolss_63 *r)
10840 {
10841         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10842         return WERR_NOT_SUPPORTED;
10843 }
10844
10845 /****************************************************************
10846  _spoolss_64
10847 ****************************************************************/
10848
10849 WERROR _spoolss_64(struct pipes_struct *p,
10850                    struct spoolss_64 *r)
10851 {
10852         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10853         return WERR_NOT_SUPPORTED;
10854 }
10855
10856 /****************************************************************
10857  _spoolss_65
10858 ****************************************************************/
10859
10860 WERROR _spoolss_65(struct pipes_struct *p,
10861                    struct spoolss_65 *r)
10862 {
10863         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10864         return WERR_NOT_SUPPORTED;
10865 }
10866
10867 /****************************************************************
10868  _spoolss_GetCorePrinterDrivers
10869 ****************************************************************/
10870
10871 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10872                                       struct spoolss_GetCorePrinterDrivers *r)
10873 {
10874         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10875         return WERR_NOT_SUPPORTED;
10876 }
10877
10878 /****************************************************************
10879  _spoolss_67
10880 ****************************************************************/
10881
10882 WERROR _spoolss_67(struct pipes_struct *p,
10883                    struct spoolss_67 *r)
10884 {
10885         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10886         return WERR_NOT_SUPPORTED;
10887 }
10888
10889 /****************************************************************
10890  _spoolss_GetPrinterDriverPackagePath
10891 ****************************************************************/
10892
10893 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10894                                             struct spoolss_GetPrinterDriverPackagePath *r)
10895 {
10896         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10897         return WERR_NOT_SUPPORTED;
10898 }
10899
10900 /****************************************************************
10901  _spoolss_69
10902 ****************************************************************/
10903
10904 WERROR _spoolss_69(struct pipes_struct *p,
10905                    struct spoolss_69 *r)
10906 {
10907         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10908         return WERR_NOT_SUPPORTED;
10909 }
10910
10911 /****************************************************************
10912  _spoolss_6a
10913 ****************************************************************/
10914
10915 WERROR _spoolss_6a(struct pipes_struct *p,
10916                    struct spoolss_6a *r)
10917 {
10918         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10919         return WERR_NOT_SUPPORTED;
10920 }
10921
10922 /****************************************************************
10923  _spoolss_6b
10924 ****************************************************************/
10925
10926 WERROR _spoolss_6b(struct pipes_struct *p,
10927                    struct spoolss_6b *r)
10928 {
10929         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10930         return WERR_NOT_SUPPORTED;
10931 }
10932
10933 /****************************************************************
10934  _spoolss_6c
10935 ****************************************************************/
10936
10937 WERROR _spoolss_6c(struct pipes_struct *p,
10938                    struct spoolss_6c *r)
10939 {
10940         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10941         return WERR_NOT_SUPPORTED;
10942 }
10943
10944 /****************************************************************
10945  _spoolss_6d
10946 ****************************************************************/
10947
10948 WERROR _spoolss_6d(struct pipes_struct *p,
10949                    struct spoolss_6d *r)
10950 {
10951         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10952         return WERR_NOT_SUPPORTED;
10953 }