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