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