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