b67d57180737a9b816b2ca08bb4f97be148640c6
[mat/samba.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "include/printing.h"
42 #include "secrets.h"
43 #include "../librpc/gen_ndr/netlogon.h"
44 #include "rpc_misc.h"
45 #include "printing/notify.h"
46 #include "serverid.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "smbd/globals.h"
50 #include "auth.h"
51 #include "messages.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
53 #include "util_tdb.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
58 #include "../libcli/smb/smbXcli_base.h"
59
60 /* macros stolen from s4 spoolss server */
61 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
62         ((info)?ndr_size_##fn(info, level, 0):0)
63
64 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
65         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
66
67 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
68         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
69
70 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
71
72 #undef DBGC_CLASS
73 #define DBGC_CLASS DBGC_RPC_SRV
74
75 #ifndef MAX_OPEN_PRINTER_EXS
76 #define MAX_OPEN_PRINTER_EXS 50
77 #endif
78
79 struct notify_back_channel;
80
81 /* structure to store the printer handles */
82 /* and a reference to what it's pointing to */
83 /* and the notify info asked about */
84 /* that's the central struct */
85 struct printer_handle {
86         struct printer_handle *prev, *next;
87         bool document_started;
88         bool page_started;
89         uint32 jobid; /* jobid in printing backend */
90         int printer_type;
91         const char *servername;
92         fstring sharename;
93         uint32 type;
94         uint32 access_granted;
95         struct {
96                 uint32 flags;
97                 uint32 options;
98                 fstring localmachine;
99                 uint32 printerlocal;
100                 struct spoolss_NotifyOption *option;
101                 struct policy_handle cli_hnd;
102                 struct notify_back_channel *cli_chan;
103                 uint32 change;
104                 /* are we in a FindNextPrinterChangeNotify() call? */
105                 bool fnpcn;
106                 struct messaging_context *msg_ctx;
107         } notify;
108         struct {
109                 fstring machine;
110                 fstring user;
111         } client;
112
113         /* devmode sent in the OpenPrinter() call */
114         struct spoolss_DeviceMode *devmode;
115
116         /* TODO cache the printer info2 structure */
117         struct spoolss_PrinterInfo2 *info2;
118
119 };
120
121 static struct printer_handle *printers_list;
122
123 struct printer_session_counter {
124         struct printer_session_counter *next;
125         struct printer_session_counter *prev;
126
127         int snum;
128         uint32_t counter;
129 };
130
131 static struct printer_session_counter *counter_list;
132
133 struct notify_back_channel {
134         struct notify_back_channel *prev, *next;
135
136         /* associated client */
137         struct sockaddr_storage client_address;
138
139         /* print notify back-channel pipe handle*/
140         struct rpc_pipe_client *cli_pipe;
141         uint32_t active_connections;
142 };
143
144 static struct notify_back_channel *back_channels;
145
146 /* Map generic permissions to printer object specific permissions */
147
148 const struct standard_mapping printer_std_mapping = {
149         PRINTER_READ,
150         PRINTER_WRITE,
151         PRINTER_EXECUTE,
152         PRINTER_ALL_ACCESS
153 };
154
155 /* Map generic permissions to print server object specific permissions */
156
157 const struct standard_mapping printserver_std_mapping = {
158         SERVER_READ,
159         SERVER_WRITE,
160         SERVER_EXECUTE,
161         SERVER_ALL_ACCESS
162 };
163
164 /* API table for Xcv Monitor functions */
165
166 struct xcv_api_table {
167         const char *name;
168         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
169 };
170
171 static void prune_printername_cache(void);
172
173 /********************************************************************
174  * Canonicalize servername.
175  ********************************************************************/
176
177 static const char *canon_servername(const char *servername)
178 {
179         const char *pservername = servername;
180         while (*pservername == '\\') {
181                 pservername++;
182         }
183         return pservername;
184 }
185
186 /* translate between internal status numbers and NT status numbers */
187 static int nt_printj_status(int v)
188 {
189         switch (v) {
190         case LPQ_QUEUED:
191                 return 0;
192         case LPQ_PAUSED:
193                 return JOB_STATUS_PAUSED;
194         case LPQ_SPOOLING:
195                 return JOB_STATUS_SPOOLING;
196         case LPQ_PRINTING:
197                 return JOB_STATUS_PRINTING;
198         case LPQ_ERROR:
199                 return JOB_STATUS_ERROR;
200         case LPQ_DELETING:
201                 return JOB_STATUS_DELETING;
202         case LPQ_OFFLINE:
203                 return JOB_STATUS_OFFLINE;
204         case LPQ_PAPEROUT:
205                 return JOB_STATUS_PAPEROUT;
206         case LPQ_PRINTED:
207                 return JOB_STATUS_PRINTED;
208         case LPQ_DELETED:
209                 return JOB_STATUS_DELETED;
210         case LPQ_BLOCKED:
211                 return JOB_STATUS_BLOCKED_DEVQ;
212         case LPQ_USER_INTERVENTION:
213                 return JOB_STATUS_USER_INTERVENTION;
214         }
215         return 0;
216 }
217
218 static int nt_printq_status(int v)
219 {
220         switch (v) {
221         case LPQ_PAUSED:
222                 return PRINTER_STATUS_PAUSED;
223         case LPQ_QUEUED:
224         case LPQ_SPOOLING:
225         case LPQ_PRINTING:
226                 return 0;
227         }
228         return 0;
229 }
230
231 /***************************************************************************
232  Disconnect from the client
233 ****************************************************************************/
234
235 static void srv_spoolss_replycloseprinter(int snum,
236                                           struct printer_handle *prn_hnd)
237 {
238         WERROR result;
239         NTSTATUS status;
240
241         /*
242          * Tell the specific printing tdb we no longer want messages for this printer
243          * by deregistering our PID.
244          */
245
246         if (!print_notify_deregister_pid(snum)) {
247                 DEBUG(0, ("Failed to register our pid for printer %s\n",
248                           lp_const_servicename(snum)));
249         }
250
251         /* weird if the test succeeds !!! */
252         if (prn_hnd->notify.cli_chan == NULL ||
253             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
254             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
255             prn_hnd->notify.cli_chan->active_connections == 0) {
256                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
257                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
258                 TALLOC_FREE(prn_hnd->notify.cli_chan);
259                 return;
260         }
261
262         status = dcerpc_spoolss_ReplyClosePrinter(
263                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
264                                         talloc_tos(),
265                                         &prn_hnd->notify.cli_hnd,
266                                         &result);
267         if (!NT_STATUS_IS_OK(status)) {
268                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
269                           nt_errstr(status)));
270                 result = ntstatus_to_werror(status);
271         } else if (!W_ERROR_IS_OK(result)) {
272                 DEBUG(0, ("reply_close_printer failed [%s].\n",
273                           win_errstr(result)));
274         }
275
276         /* if it's the last connection, deconnect the IPC$ share */
277         if (prn_hnd->notify.cli_chan->active_connections == 1) {
278
279                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
280                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
281                 TALLOC_FREE(prn_hnd->notify.cli_chan);
282
283                 if (prn_hnd->notify.msg_ctx != NULL) {
284                         messaging_deregister(prn_hnd->notify.msg_ctx,
285                                              MSG_PRINTER_NOTIFY2, NULL);
286                 }
287         }
288
289         if (prn_hnd->notify.cli_chan) {
290                 prn_hnd->notify.cli_chan->active_connections--;
291                 prn_hnd->notify.cli_chan = NULL;
292         }
293 }
294
295 /****************************************************************************
296  Functions to free a printer entry datastruct.
297 ****************************************************************************/
298
299 static int printer_entry_destructor(struct printer_handle *Printer)
300 {
301         if (Printer->notify.cli_chan != NULL &&
302             Printer->notify.cli_chan->active_connections > 0) {
303                 int snum = -1;
304
305                 switch(Printer->printer_type) {
306                 case SPLHND_SERVER:
307                         srv_spoolss_replycloseprinter(snum, Printer);
308                         break;
309
310                 case SPLHND_PRINTER:
311                         snum = print_queue_snum(Printer->sharename);
312                         if (snum != -1) {
313                                 srv_spoolss_replycloseprinter(snum, Printer);
314                         }
315                         break;
316                 default:
317                         break;
318                 }
319         }
320
321         Printer->notify.flags=0;
322         Printer->notify.options=0;
323         Printer->notify.localmachine[0]='\0';
324         Printer->notify.printerlocal=0;
325         TALLOC_FREE(Printer->notify.option);
326         TALLOC_FREE(Printer->devmode);
327
328         /* Remove from the internal list. */
329         DLIST_REMOVE(printers_list, Printer);
330         return 0;
331 }
332
333 /****************************************************************************
334   find printer index by handle
335 ****************************************************************************/
336
337 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
338                                                         struct policy_handle *hnd)
339 {
340         struct printer_handle *find_printer = NULL;
341
342         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
343                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
344                 return NULL;
345         }
346
347         return find_printer;
348 }
349
350 /****************************************************************************
351  Close printer index by handle.
352 ****************************************************************************/
353
354 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
355 {
356         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
357
358         if (!Printer) {
359                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
360                         OUR_HANDLE(hnd)));
361                 return false;
362         }
363
364         close_policy_hnd(p, hnd);
365
366         return true;
367 }
368
369 /****************************************************************************
370  Delete a printer given a handle.
371 ****************************************************************************/
372
373 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
374                                   const char *sharename,
375                                   struct messaging_context *msg_ctx)
376 {
377         char *cmd = lp_deleteprinter_cmd();
378         char *command = NULL;
379         int ret;
380         bool is_print_op = false;
381
382         /* can't fail if we don't try */
383
384         if ( !*cmd )
385                 return WERR_OK;
386
387         command = talloc_asprintf(ctx,
388                         "%s \"%s\"",
389                         cmd, sharename);
390         if (!command) {
391                 return WERR_NOMEM;
392         }
393         if ( token )
394                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
395
396         DEBUG(10,("Running [%s]\n", command));
397
398         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
399
400         if ( is_print_op )
401                 become_root();
402
403         if ( (ret = smbrun(command, NULL)) == 0 ) {
404                 /* Tell everyone we updated smb.conf. */
405                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
406         }
407
408         if ( is_print_op )
409                 unbecome_root();
410
411         /********** END SePrintOperatorPrivlege BLOCK **********/
412
413         DEBUGADD(10,("returned [%d]\n", ret));
414
415         TALLOC_FREE(command);
416
417         if (ret != 0)
418                 return WERR_BADFID; /* What to return here? */
419
420         return WERR_OK;
421 }
422
423 /****************************************************************************
424  Delete a printer given a handle.
425 ****************************************************************************/
426
427 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
428 {
429         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
430         WERROR result;
431
432         if (!Printer) {
433                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
434                         OUR_HANDLE(hnd)));
435                 return WERR_BADFID;
436         }
437
438         /*
439          * It turns out that Windows allows delete printer on a handle
440          * opened by an admin user, then used on a pipe handle created
441          * by an anonymous user..... but they're working on security.... riiight !
442          * JRA.
443          */
444
445         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
446                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
447                 return WERR_ACCESS_DENIED;
448         }
449
450         /* this does not need a become root since the access check has been
451            done on the handle already */
452
453         result = winreg_delete_printer_key_internal(p->mem_ctx,
454                                            get_session_info_system(),
455                                            p->msg_ctx,
456                                            Printer->sharename,
457                                            "");
458         if (!W_ERROR_IS_OK(result)) {
459                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
460                 return WERR_BADFID;
461         }
462
463         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
464                                      Printer->sharename, p->msg_ctx);
465         if (!W_ERROR_IS_OK(result)) {
466                 return result;
467         }
468         prune_printername_cache();
469         return WERR_OK;
470 }
471
472 /****************************************************************************
473  Return the snum of a printer corresponding to an handle.
474 ****************************************************************************/
475
476 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
477                              int *number, struct share_params **params)
478 {
479         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
480
481         if (!Printer) {
482                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
483                         OUR_HANDLE(hnd)));
484                 return false;
485         }
486
487         switch (Printer->printer_type) {
488                 case SPLHND_PRINTER:
489                         DEBUG(4,("short name:%s\n", Printer->sharename));
490                         *number = print_queue_snum(Printer->sharename);
491                         return (*number != -1);
492                 case SPLHND_SERVER:
493                         return false;
494                 default:
495                         return false;
496         }
497 }
498
499 /****************************************************************************
500  Set printer handle type.
501  Check if it's \\server or \\server\printer
502 ****************************************************************************/
503
504 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
505 {
506         DEBUG(3,("Setting printer type=%s\n", handlename));
507
508         /* it's a print server */
509         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
510                 DEBUGADD(4,("Printer is a print server\n"));
511                 Printer->printer_type = SPLHND_SERVER;
512         }
513         /* it's a printer (set_printer_hnd_name() will handle port monitors */
514         else {
515                 DEBUGADD(4,("Printer is a printer\n"));
516                 Printer->printer_type = SPLHND_PRINTER;
517         }
518
519         return true;
520 }
521
522 static void prune_printername_cache_fn(const char *key, const char *value,
523                                        time_t timeout, void *private_data)
524 {
525         gencache_del(key);
526 }
527
528 static void prune_printername_cache(void)
529 {
530         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
531 }
532
533 /****************************************************************************
534  Set printer handle name..  Accept names like \\server, \\server\printer,
535  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
536  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
537  XcvDataPort() interface.
538 ****************************************************************************/
539
540 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
541                                    const struct auth_session_info *session_info,
542                                    struct messaging_context *msg_ctx,
543                                    struct printer_handle *Printer,
544                                    const char *handlename)
545 {
546         int snum;
547         int n_services=lp_numservices();
548         char *aprinter;
549         const char *printername;
550         const char *servername = NULL;
551         fstring sname;
552         bool found = false;
553         struct spoolss_PrinterInfo2 *info2 = NULL;
554         WERROR result;
555         char *p;
556
557         /*
558          * Hopefully nobody names his printers like this. Maybe \ or ,
559          * are illegal in printer names even?
560          */
561         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
562         char *cache_key;
563         char *tmp;
564
565         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
566                 (unsigned long)strlen(handlename)));
567
568         aprinter = discard_const_p(char, handlename);
569         if ( *handlename == '\\' ) {
570                 servername = canon_servername(handlename);
571                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
572                         *aprinter = '\0';
573                         aprinter++;
574                 }
575                 if (!is_myname_or_ipaddr(servername)) {
576                         return WERR_INVALID_PRINTER_NAME;
577                 }
578                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
579                 if (Printer->servername == NULL) {
580                         return WERR_NOMEM;
581                 }
582         }
583
584         if (Printer->printer_type == SPLHND_SERVER) {
585                 return WERR_OK;
586         }
587
588         if (Printer->printer_type != SPLHND_PRINTER) {
589                 return WERR_INVALID_HANDLE;
590         }
591
592         DEBUGADD(5, ("searching for [%s]\n", aprinter));
593
594         p = strchr(aprinter, ',');
595         if (p != NULL) {
596                 char *p2 = p;
597                 p++;
598                 if (*p == ' ') {
599                         p++;
600                 }
601                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
602                         *p2 = '\0';
603                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
604                         *p2 = '\0';
605                 }
606         }
607
608         if (p) {
609                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
610         }
611
612         /* check for the Port Monitor Interface */
613         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
614                 Printer->printer_type = SPLHND_PORTMON_TCP;
615                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
616                 found = true;
617         }
618         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
619                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
620                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
621                 found = true;
622         }
623
624         /*
625          * With hundreds of printers, the "for" loop iterating all
626          * shares can be quite expensive, as it is done on every
627          * OpenPrinter. The loop maps "aprinter" to "sname", the
628          * result of which we cache in gencache.
629          */
630
631         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
632                                     aprinter);
633         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
634
635                 found = (strcmp(tmp, printer_not_found) != 0);
636                 if (!found) {
637                         DEBUG(4, ("Printer %s not found\n", aprinter));
638                         SAFE_FREE(tmp);
639                         return WERR_INVALID_PRINTER_NAME;
640                 }
641                 fstrcpy(sname, tmp);
642                 SAFE_FREE(tmp);
643         }
644
645         /* Search all sharenames first as this is easier than pulling
646            the printer_info_2 off of disk. Don't use find_service() since
647            that calls out to map_username() */
648
649         /* do another loop to look for printernames */
650         for (snum = 0; !found && snum < n_services; snum++) {
651                 const char *printer = lp_const_servicename(snum);
652
653                 /* no point going on if this is not a printer */
654                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
655                         continue;
656                 }
657
658                 /* ignore [printers] share */
659                 if (strequal(printer, "printers")) {
660                         continue;
661                 }
662
663                 fstrcpy(sname, printer);
664                 if (strequal(aprinter, printer)) {
665                         found = true;
666                         break;
667                 }
668
669                 /* no point looking up the printer object if
670                    we aren't allowing printername != sharename */
671                 if (lp_force_printername(snum)) {
672                         continue;
673                 }
674
675                 result = winreg_get_printer_internal(mem_ctx,
676                                             session_info,
677                                             msg_ctx,
678                                             sname,
679                                             &info2);
680                 if ( !W_ERROR_IS_OK(result) ) {
681                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
682                                  sname, win_errstr(result)));
683                         continue;
684                 }
685
686                 printername = strrchr(info2->printername, '\\');
687                 if (printername == NULL) {
688                         printername = info2->printername;
689                 } else {
690                         printername++;
691                 }
692
693                 if (strequal(printername, aprinter)) {
694                         found = true;
695                         break;
696                 }
697
698                 DEBUGADD(10, ("printername: %s\n", printername));
699
700                 TALLOC_FREE(info2);
701         }
702
703         if ( !found ) {
704                 if (cache_key != NULL) {
705                         gencache_set(cache_key, printer_not_found,
706                                      time(NULL)+300);
707                         TALLOC_FREE(cache_key);
708                 }
709                 DEBUGADD(4,("Printer not found\n"));
710                 return WERR_INVALID_PRINTER_NAME;
711         }
712
713         if (cache_key != NULL) {
714                 gencache_set(cache_key, sname, time(NULL)+300);
715                 TALLOC_FREE(cache_key);
716         }
717
718         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
719
720         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
721
722         return WERR_OK;
723 }
724
725 /****************************************************************************
726  Find first available printer slot. creates a printer handle for you.
727  ****************************************************************************/
728
729 static WERROR open_printer_hnd(struct pipes_struct *p,
730                                struct policy_handle *hnd,
731                                const char *name,
732                                uint32_t access_granted)
733 {
734         struct printer_handle *new_printer;
735         WERROR result;
736
737         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
738
739         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
740         if (new_printer == NULL) {
741                 return WERR_NOMEM;
742         }
743         talloc_set_destructor(new_printer, printer_entry_destructor);
744
745         /* This also steals the printer_handle on the policy_handle */
746         if (!create_policy_hnd(p, hnd, new_printer)) {
747                 TALLOC_FREE(new_printer);
748                 return WERR_INVALID_HANDLE;
749         }
750
751         /* Add to the internal list. */
752         DLIST_ADD(printers_list, new_printer);
753
754         new_printer->notify.option=NULL;
755
756         if (!set_printer_hnd_printertype(new_printer, name)) {
757                 close_printer_handle(p, hnd);
758                 return WERR_INVALID_HANDLE;
759         }
760
761         result = set_printer_hnd_name(p->mem_ctx,
762                                       get_session_info_system(),
763                                       p->msg_ctx,
764                                       new_printer, name);
765         if (!W_ERROR_IS_OK(result)) {
766                 close_printer_handle(p, hnd);
767                 return result;
768         }
769
770         new_printer->access_granted = access_granted;
771
772         DEBUG(5, ("%d printer handles active\n",
773                   (int)num_pipe_handles(p)));
774
775         return WERR_OK;
776 }
777
778 /***************************************************************************
779  check to see if the client motify handle is monitoring the notification
780  given by (notify_type, notify_field).
781  **************************************************************************/
782
783 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
784                                       uint16_t notify_field)
785 {
786         return true;
787 }
788
789 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
790                                 uint16_t notify_field)
791 {
792         struct spoolss_NotifyOption *option = p->notify.option;
793         uint32_t i, j;
794
795         /*
796          * Flags should always be zero when the change notify
797          * is registered by the client's spooler.  A user Win32 app
798          * might use the flags though instead of the NOTIFY_OPTION_INFO
799          * --jerry
800          */
801
802         if (!option) {
803                 return false;
804         }
805
806         if (p->notify.flags)
807                 return is_monitoring_event_flags(
808                         p->notify.flags, notify_type, notify_field);
809
810         for (i = 0; i < option->count; i++) {
811
812                 /* Check match for notify_type */
813
814                 if (option->types[i].type != notify_type)
815                         continue;
816
817                 /* Check match for field */
818
819                 for (j = 0; j < option->types[i].count; j++) {
820                         if (option->types[i].fields[j].field == notify_field) {
821                                 return true;
822                         }
823                 }
824         }
825
826         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
827                    p->servername, p->sharename, notify_type, notify_field));
828
829         return false;
830 }
831
832 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
833         _data->data.integer[0] = _integer; \
834         _data->data.integer[1] = 0;
835
836
837 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
838         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
839         if (!_data->data.string.string) {\
840                 _data->data.string.size = 0; \
841         } \
842         _data->data.string.size = strlen_m_term(_p) * 2;
843
844 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
845         _data->data.devmode.devmode = _devmode;
846
847 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
848         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
849         if (!_data->data.sd.sd) { \
850                 _data->data.sd.sd_size = 0; \
851         } \
852         _data->data.sd.sd_size = \
853                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
854
855 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
856                                    struct tm *t,
857                                    const char **pp,
858                                    uint32_t *plen)
859 {
860         struct spoolss_Time st;
861         uint32_t len = 16;
862         char *p;
863
864         if (!init_systemtime(&st, t)) {
865                 return;
866         }
867
868         p = talloc_array(mem_ctx, char, len);
869         if (!p) {
870                 return;
871         }
872
873         /*
874          * Systemtime must be linearized as a set of UINT16's.
875          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
876          */
877
878         SSVAL(p, 0, st.year);
879         SSVAL(p, 2, st.month);
880         SSVAL(p, 4, st.day_of_week);
881         SSVAL(p, 6, st.day);
882         SSVAL(p, 8, st.hour);
883         SSVAL(p, 10, st.minute);
884         SSVAL(p, 12, st.second);
885         SSVAL(p, 14, st.millisecond);
886
887         *pp = p;
888         *plen = len;
889 }
890
891 /* Convert a notification message to a struct spoolss_Notify */
892
893 static void notify_one_value(struct spoolss_notify_msg *msg,
894                              struct spoolss_Notify *data,
895                              TALLOC_CTX *mem_ctx)
896 {
897         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
898 }
899
900 static void notify_string(struct spoolss_notify_msg *msg,
901                           struct spoolss_Notify *data,
902                           TALLOC_CTX *mem_ctx)
903 {
904         /* The length of the message includes the trailing \0 */
905
906         data->data.string.size = msg->len * 2;
907         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
908         if (!data->data.string.string) {
909                 data->data.string.size = 0;
910                 return;
911         }
912 }
913
914 static void notify_system_time(struct spoolss_notify_msg *msg,
915                                struct spoolss_Notify *data,
916                                TALLOC_CTX *mem_ctx)
917 {
918         data->data.string.string = NULL;
919         data->data.string.size = 0;
920
921         if (msg->len != sizeof(time_t)) {
922                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
923                           msg->len));
924                 return;
925         }
926
927         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
928                                &data->data.string.string,
929                                &data->data.string.size);
930 }
931
932 struct notify2_message_table {
933         const char *name;
934         void (*fn)(struct spoolss_notify_msg *msg,
935                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
936 };
937
938 static struct notify2_message_table printer_notify_table[] = {
939         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
940         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
941         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
942         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
943         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
944         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
945         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
946         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
947         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
948         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
949         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
950         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
951         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
952         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
953         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
954         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
955         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
956         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
957         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
958 };
959
960 static struct notify2_message_table job_notify_table[] = {
961         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
962         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
963         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
964         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
965         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
966         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
967         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
968         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
969         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
970         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
971         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
972         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
973         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
974         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
975         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
976         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
977         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
978         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
979         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
980         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
981         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
982         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
983         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
984         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
985 };
986
987
988 /***********************************************************************
989  Allocate talloc context for container object
990  **********************************************************************/
991
992 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
993 {
994         if ( !ctr )
995                 return;
996
997         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
998
999         return;
1000 }
1001
1002 /***********************************************************************
1003  release all allocated memory and zero out structure
1004  **********************************************************************/
1005
1006 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1007 {
1008         if ( !ctr )
1009                 return;
1010
1011         if ( ctr->ctx )
1012                 talloc_destroy(ctr->ctx);
1013
1014         ZERO_STRUCTP(ctr);
1015
1016         return;
1017 }
1018
1019 /***********************************************************************
1020  **********************************************************************/
1021
1022 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1023 {
1024         if ( !ctr )
1025                 return NULL;
1026
1027         return ctr->ctx;
1028 }
1029
1030 /***********************************************************************
1031  **********************************************************************/
1032
1033 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1034 {
1035         if ( !ctr || !ctr->msg_groups )
1036                 return NULL;
1037
1038         if ( idx >= ctr->num_groups )
1039                 return NULL;
1040
1041         return &ctr->msg_groups[idx];
1042
1043 }
1044
1045 /***********************************************************************
1046  How many groups of change messages do we have ?
1047  **********************************************************************/
1048
1049 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1050 {
1051         if ( !ctr )
1052                 return 0;
1053
1054         return ctr->num_groups;
1055 }
1056
1057 /***********************************************************************
1058  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1059  **********************************************************************/
1060
1061 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1062 {
1063         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1064         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1065         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1066         int                             i, new_slot;
1067
1068         if ( !ctr || !msg )
1069                 return 0;
1070
1071         /* loop over all groups looking for a matching printer name */
1072
1073         for ( i=0; i<ctr->num_groups; i++ ) {
1074                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1075                         break;
1076         }
1077
1078         /* add a new group? */
1079
1080         if ( i == ctr->num_groups ) {
1081                 ctr->num_groups++;
1082
1083                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1084                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1085                         return 0;
1086                 }
1087                 ctr->msg_groups = groups;
1088
1089                 /* clear the new entry and set the printer name */
1090
1091                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1092                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1093         }
1094
1095         /* add the change messages; 'i' is the correct index now regardless */
1096
1097         msg_grp = &ctr->msg_groups[i];
1098
1099         msg_grp->num_msgs++;
1100
1101         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1102                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1103                 return 0;
1104         }
1105         msg_grp->msgs = msg_list;
1106
1107         new_slot = msg_grp->num_msgs-1;
1108         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1109
1110         /* need to allocate own copy of data */
1111
1112         if ( msg->len != 0 )
1113                 msg_grp->msgs[new_slot].notify.data = (char *)
1114                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1115
1116         return ctr->num_groups;
1117 }
1118
1119 static void construct_info_data(struct spoolss_Notify *info_data,
1120                                 enum spoolss_NotifyType type,
1121                                 uint16_t field, int id);
1122
1123 /***********************************************************************
1124  Send a change notication message on all handles which have a call
1125  back registered
1126  **********************************************************************/
1127
1128 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1129                                   struct printer_handle *prn_hnd,
1130                                   SPOOLSS_NOTIFY_MSG *messages,
1131                                   uint32_t num_msgs,
1132                                   struct spoolss_Notify **_notifies,
1133                                   int *_count)
1134 {
1135         struct spoolss_Notify *notifies;
1136         SPOOLSS_NOTIFY_MSG *msg;
1137         int count = 0;
1138         uint32_t id;
1139         int i;
1140
1141         notifies = talloc_zero_array(mem_ctx,
1142                                      struct spoolss_Notify, num_msgs);
1143         if (!notifies) {
1144                 return ENOMEM;
1145         }
1146
1147         for (i = 0; i < num_msgs; i++) {
1148
1149                 msg = &messages[i];
1150
1151                 /* Are we monitoring this event? */
1152
1153                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1154                         continue;
1155                 }
1156
1157                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1158                            "for printer [%s]\n",
1159                            msg->type, msg->field, prn_hnd->sharename));
1160
1161                 /*
1162                  * if the is a printer notification handle and not a job
1163                  * notification type, then set the id to 0.
1164                  * Otherwise just use what was specified in the message.
1165                  *
1166                  * When registering change notification on a print server
1167                  * handle we always need to send back the id (snum) matching
1168                  * the printer for which the change took place.
1169                  * For change notify registered on a printer handle,
1170                  * this does not matter and the id should be 0.
1171                  *
1172                  * --jerry
1173                  */
1174
1175                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1176                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1177                         id = 0;
1178                 } else {
1179                         id = msg->id;
1180                 }
1181
1182                 /* Convert unix jobid to smb jobid */
1183
1184                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1185                         id = sysjob_to_jobid(msg->id);
1186
1187                         if (id == -1) {
1188                                 DEBUG(3, ("no such unix jobid %d\n",
1189                                           msg->id));
1190                                 continue;
1191                         }
1192                 }
1193
1194                 construct_info_data(&notifies[count],
1195                                     msg->type, msg->field, id);
1196
1197                 switch(msg->type) {
1198                 case PRINTER_NOTIFY_TYPE:
1199                         if (printer_notify_table[msg->field].fn) {
1200                                 printer_notify_table[msg->field].fn(msg,
1201                                                 &notifies[count], mem_ctx);
1202                         }
1203                         break;
1204
1205                 case JOB_NOTIFY_TYPE:
1206                         if (job_notify_table[msg->field].fn) {
1207                                 job_notify_table[msg->field].fn(msg,
1208                                                 &notifies[count], mem_ctx);
1209                         }
1210                         break;
1211
1212                 default:
1213                         DEBUG(5, ("Unknown notification type %d\n",
1214                                   msg->type));
1215                         continue;
1216                 }
1217
1218                 count++;
1219         }
1220
1221         *_notifies = notifies;
1222         *_count = count;
1223
1224         return 0;
1225 }
1226
1227 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1228                                 struct printer_handle *prn_hnd,
1229                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1230 {
1231         struct spoolss_Notify *notifies;
1232         int count = 0;
1233         union spoolss_ReplyPrinterInfo info;
1234         struct spoolss_NotifyInfo info0;
1235         uint32_t reply_result;
1236         NTSTATUS status;
1237         WERROR werr;
1238         int ret;
1239
1240         /* Is there notification on this handle? */
1241         if (prn_hnd->notify.cli_chan == NULL ||
1242             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1243             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1244             prn_hnd->notify.cli_chan->active_connections == 0) {
1245                 return 0;
1246         }
1247
1248         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1249                    prn_hnd->servername, prn_hnd->sharename));
1250
1251         /* For this printer? Print servers always receive notifications. */
1252         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1253             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1254                 return 0;
1255         }
1256
1257         DEBUG(10,("Our printer\n"));
1258
1259         /* build the array of change notifications */
1260         ret = build_notify2_messages(mem_ctx, prn_hnd,
1261                                      msg_group->msgs,
1262                                      msg_group->num_msgs,
1263                                      &notifies, &count);
1264         if (ret) {
1265                 return ret;
1266         }
1267
1268         info0.version   = 0x2;
1269         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1270         info0.count     = count;
1271         info0.notifies  = notifies;
1272
1273         info.info0 = &info0;
1274
1275         status = dcerpc_spoolss_RouterReplyPrinterEx(
1276                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1277                                 mem_ctx,
1278                                 &prn_hnd->notify.cli_hnd,
1279                                 prn_hnd->notify.change, /* color */
1280                                 prn_hnd->notify.flags,
1281                                 &reply_result,
1282                                 0, /* reply_type, must be 0 */
1283                                 info, &werr);
1284         if (!NT_STATUS_IS_OK(status)) {
1285                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1286                           "failed: %s\n",
1287                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1288                           nt_errstr(status)));
1289                 werr = ntstatus_to_werror(status);
1290         } else if (!W_ERROR_IS_OK(werr)) {
1291                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1292                           "failed: %s\n",
1293                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1294                           win_errstr(werr)));
1295         }
1296         switch (reply_result) {
1297         case 0:
1298                 break;
1299         case PRINTER_NOTIFY_INFO_DISCARDED:
1300         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1301         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1302                 break;
1303         default:
1304                 break;
1305         }
1306
1307         return 0;
1308 }
1309
1310 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1311 {
1312         struct printer_handle    *p;
1313         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1314         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1315         int ret;
1316
1317         if ( !msg_group ) {
1318                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1319                 return;
1320         }
1321
1322         if (!msg_group->msgs) {
1323                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1324                 return;
1325         }
1326
1327         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1328
1329         /* loop over all printers */
1330
1331         for (p = printers_list; p; p = p->next) {
1332                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1333                 if (ret) {
1334                         goto done;
1335                 }
1336         }
1337
1338 done:
1339         DEBUG(8,("send_notify2_changes: Exit...\n"));
1340         return;
1341 }
1342
1343 /***********************************************************************
1344  **********************************************************************/
1345
1346 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1347 {
1348
1349         uint32_t tv_sec, tv_usec;
1350         size_t offset = 0;
1351
1352         /* Unpack message */
1353
1354         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1355                              msg->printer);
1356
1357         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1358                                 &tv_sec, &tv_usec,
1359                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1360
1361         if (msg->len == 0)
1362                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1363                            &msg->notify.value[0], &msg->notify.value[1]);
1364         else
1365                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1366                            &msg->len, &msg->notify.data);
1367
1368         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1369                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1370
1371         tv->tv_sec = tv_sec;
1372         tv->tv_usec = tv_usec;
1373
1374         if (msg->len == 0)
1375                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1376                           msg->notify.value[1]));
1377         else
1378                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1379
1380         return true;
1381 }
1382
1383 /********************************************************************
1384  Receive a notify2 message list
1385  ********************************************************************/
1386
1387 static void receive_notify2_message_list(struct messaging_context *msg,
1388                                          void *private_data,
1389                                          uint32_t msg_type,
1390                                          struct server_id server_id,
1391                                          DATA_BLOB *data)
1392 {
1393         size_t                  msg_count, i;
1394         char                    *buf = (char *)data->data;
1395         char                    *msg_ptr;
1396         size_t                  msg_len;
1397         SPOOLSS_NOTIFY_MSG      notify;
1398         SPOOLSS_NOTIFY_MSG_CTR  messages;
1399         int                     num_groups;
1400
1401         if (data->length < 4) {
1402                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1403                 return;
1404         }
1405
1406         msg_count = IVAL(buf, 0);
1407         msg_ptr = buf + 4;
1408
1409         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1410
1411         if (msg_count == 0) {
1412                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1413                 return;
1414         }
1415
1416         /* initialize the container */
1417
1418         ZERO_STRUCT( messages );
1419         notify_msg_ctr_init( &messages );
1420
1421         /*
1422          * build message groups for each printer identified
1423          * in a change_notify msg.  Remember that a PCN message
1424          * includes the handle returned for the srv_spoolss_replyopenprinter()
1425          * call.  Therefore messages are grouped according to printer handle.
1426          */
1427
1428         for ( i=0; i<msg_count; i++ ) {
1429                 struct timeval msg_tv;
1430
1431                 if (msg_ptr + 4 - buf > data->length) {
1432                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1433                         return;
1434                 }
1435
1436                 msg_len = IVAL(msg_ptr,0);
1437                 msg_ptr += 4;
1438
1439                 if (msg_ptr + msg_len - buf > data->length) {
1440                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1441                         return;
1442                 }
1443
1444                 /* unpack messages */
1445
1446                 ZERO_STRUCT( notify );
1447                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1448                 msg_ptr += msg_len;
1449
1450                 /* add to correct list in container */
1451
1452                 notify_msg_ctr_addmsg( &messages, &notify );
1453
1454                 /* free memory that might have been allocated by notify2_unpack_msg() */
1455
1456                 if ( notify.len != 0 )
1457                         SAFE_FREE( notify.notify.data );
1458         }
1459
1460         /* process each group of messages */
1461
1462         num_groups = notify_msg_ctr_numgroups( &messages );
1463         for ( i=0; i<num_groups; i++ )
1464                 send_notify2_changes( &messages, i );
1465
1466
1467         /* cleanup */
1468
1469         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1470                 (uint32_t)msg_count ));
1471
1472         notify_msg_ctr_destroy( &messages );
1473
1474         return;
1475 }
1476
1477 /********************************************************************
1478  Send a message to ourself about new driver being installed
1479  so we can upgrade the information for each printer bound to this
1480  driver
1481  ********************************************************************/
1482
1483 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1484                                             struct messaging_context *msg_ctx)
1485 {
1486         int len = strlen(drivername);
1487
1488         if (!len)
1489                 return false;
1490
1491         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1492                 drivername));
1493
1494         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1495                            MSG_PRINTER_DRVUPGRADE,
1496                            (const uint8_t *)drivername, len+1);
1497
1498         return true;
1499 }
1500
1501 void srv_spoolss_cleanup(void)
1502 {
1503         struct printer_session_counter *session_counter;
1504
1505         for (session_counter = counter_list;
1506              session_counter != NULL;
1507              session_counter = counter_list) {
1508                 DLIST_REMOVE(counter_list, session_counter);
1509                 TALLOC_FREE(session_counter);
1510         }
1511 }
1512
1513 /**********************************************************************
1514  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1515  over all printers, upgrading ones as necessary
1516  **********************************************************************/
1517
1518 void do_drv_upgrade_printer(struct messaging_context *msg,
1519                             void *private_data,
1520                             uint32_t msg_type,
1521                             struct server_id server_id,
1522                             DATA_BLOB *data)
1523 {
1524         TALLOC_CTX *tmp_ctx;
1525         const struct auth_session_info *session_info = get_session_info_system();
1526         struct spoolss_PrinterInfo2 *pinfo2;
1527         WERROR result;
1528         const char *drivername;
1529         int snum;
1530         int n_services = lp_numservices();
1531         struct dcerpc_binding_handle *b = NULL;
1532
1533         tmp_ctx = talloc_new(NULL);
1534         if (!tmp_ctx) return;
1535
1536         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1537         if (!drivername) {
1538                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1539                 goto done;
1540         }
1541
1542         DEBUG(10, ("do_drv_upgrade_printer: "
1543                    "Got message for new driver [%s]\n", drivername));
1544
1545         /* Iterate the printer list */
1546
1547         for (snum = 0; snum < n_services; snum++) {
1548                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1549                         continue;
1550                 }
1551
1552                 /* ignore [printers] share */
1553                 if (strequal(lp_const_servicename(snum), "printers")) {
1554                         continue;
1555                 }
1556
1557                 if (b == NULL) {
1558                         result = winreg_printer_binding_handle(tmp_ctx,
1559                                                                session_info,
1560                                                                msg,
1561                                                                &b);
1562                         if (!W_ERROR_IS_OK(result)) {
1563                                 break;
1564                         }
1565                 }
1566
1567                 result = winreg_get_printer(tmp_ctx, b,
1568                                             lp_const_servicename(snum),
1569                                             &pinfo2);
1570
1571                 if (!W_ERROR_IS_OK(result)) {
1572                         continue;
1573                 }
1574
1575                 if (!pinfo2->drivername) {
1576                         continue;
1577                 }
1578
1579                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1580                         continue;
1581                 }
1582
1583                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1584
1585                 /* all we care about currently is the change_id */
1586                 result = winreg_printer_update_changeid(tmp_ctx, b,
1587                                                         pinfo2->printername);
1588
1589                 if (!W_ERROR_IS_OK(result)) {
1590                         DEBUG(3, ("do_drv_upgrade_printer: "
1591                                   "Failed to update changeid [%s]\n",
1592                                   win_errstr(result)));
1593                 }
1594         }
1595
1596         /* all done */
1597 done:
1598         talloc_free(tmp_ctx);
1599 }
1600
1601 /********************************************************************
1602  Update the cache for all printq's with a registered client
1603  connection
1604  ********************************************************************/
1605
1606 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1607 {
1608         struct printer_handle *printer = printers_list;
1609         int snum;
1610
1611         /* loop through all printers and update the cache where
1612            a client is connected */
1613         while (printer) {
1614                 if ((printer->printer_type == SPLHND_PRINTER) &&
1615                     ((printer->notify.cli_chan != NULL) &&
1616                      (printer->notify.cli_chan->active_connections > 0))) {
1617                         snum = print_queue_snum(printer->sharename);
1618                         print_queue_status(msg_ctx, snum, NULL, NULL);
1619                 }
1620
1621                 printer = printer->next;
1622         }
1623
1624         return;
1625 }
1626
1627 /****************************************************************
1628  _spoolss_OpenPrinter
1629 ****************************************************************/
1630
1631 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1632                             struct spoolss_OpenPrinter *r)
1633 {
1634         struct spoolss_OpenPrinterEx e;
1635         WERROR werr;
1636
1637         ZERO_STRUCT(e.in.userlevel);
1638
1639         e.in.printername        = r->in.printername;
1640         e.in.datatype           = r->in.datatype;
1641         e.in.devmode_ctr        = r->in.devmode_ctr;
1642         e.in.access_mask        = r->in.access_mask;
1643         e.in.level              = 0;
1644
1645         e.out.handle            = r->out.handle;
1646
1647         werr = _spoolss_OpenPrinterEx(p, &e);
1648
1649         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1650                 /* OpenPrinterEx returns this for a bad
1651                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1652                  * instead.
1653                  */
1654                 werr = WERR_INVALID_PRINTER_NAME;
1655         }
1656
1657         return werr;
1658 }
1659
1660 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1661                               struct spoolss_DeviceMode *orig,
1662                               struct spoolss_DeviceMode **dest)
1663 {
1664         struct spoolss_DeviceMode *dm;
1665
1666         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1667         if (!dm) {
1668                 return WERR_NOMEM;
1669         }
1670
1671         /* copy all values, then duplicate strings and structs */
1672         *dm = *orig;
1673
1674         dm->devicename = talloc_strdup(dm, orig->devicename);
1675         if (!dm->devicename) {
1676                 return WERR_NOMEM;
1677         }
1678         dm->formname = talloc_strdup(dm, orig->formname);
1679         if (!dm->formname) {
1680                 return WERR_NOMEM;
1681         }
1682         if (orig->driverextra_data.data) {
1683                 dm->driverextra_data.data =
1684                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1685                                         orig->driverextra_data.length);
1686                 if (!dm->driverextra_data.data) {
1687                         return WERR_NOMEM;
1688                 }
1689         }
1690
1691         *dest = dm;
1692         return WERR_OK;
1693 }
1694
1695 /****************************************************************
1696  _spoolss_OpenPrinterEx
1697 ****************************************************************/
1698
1699 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1700                               struct spoolss_OpenPrinterEx *r)
1701 {
1702         int snum;
1703         char *raddr;
1704         char *rhost;
1705         struct printer_handle *Printer=NULL;
1706         WERROR result;
1707         int rc;
1708
1709         if (!r->in.printername) {
1710                 return WERR_INVALID_PARAM;
1711         }
1712
1713         if (!*r->in.printername) {
1714                 return WERR_INVALID_PARAM;
1715         }
1716
1717         if (r->in.level > 3) {
1718                 return WERR_INVALID_PARAM;
1719         }
1720         if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1721             (r->in.level == 2 && !r->in.userlevel.level2) ||
1722             (r->in.level == 3 && !r->in.userlevel.level3)) {
1723                 return WERR_INVALID_PARAM;
1724         }
1725
1726         /* some sanity check because you can open a printer or a print server */
1727         /* aka: \\server\printer or \\server */
1728
1729         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1730
1731         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1732         if (!W_ERROR_IS_OK(result)) {
1733                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1734                         "for printer %s\n", r->in.printername));
1735                 ZERO_STRUCTP(r->out.handle);
1736                 return result;
1737         }
1738
1739         Printer = find_printer_index_by_hnd(p, r->out.handle);
1740         if ( !Printer ) {
1741                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1742                         "handle we created for printer %s\n", r->in.printername));
1743                 close_printer_handle(p, r->out.handle);
1744                 ZERO_STRUCTP(r->out.handle);
1745                 return WERR_INVALID_PARAM;
1746         }
1747
1748         /*
1749          * First case: the user is opening the print server:
1750          *
1751          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1752          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1753          *
1754          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1755          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1756          * or if the user is listed in the smb.conf printer admin parameter.
1757          *
1758          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1759          * client view printer folder, but does not show the MSAPW.
1760          *
1761          * Note: this test needs code to check access rights here too. Jeremy
1762          * could you look at this?
1763          *
1764          * Second case: the user is opening a printer:
1765          * NT doesn't let us connect to a printer if the connecting user
1766          * doesn't have print permission.
1767          *
1768          * Third case: user is opening a Port Monitor
1769          * access checks same as opening a handle to the print server.
1770          */
1771
1772         switch (Printer->printer_type )
1773         {
1774         case SPLHND_SERVER:
1775         case SPLHND_PORTMON_TCP:
1776         case SPLHND_PORTMON_LOCAL:
1777                 /* Printserver handles use global struct... */
1778
1779                 snum = -1;
1780
1781                 /* Map standard access rights to object specific access rights */
1782
1783                 se_map_standard(&r->in.access_mask,
1784                                 &printserver_std_mapping);
1785
1786                 /* Deny any object specific bits that don't apply to print
1787                    servers (i.e printer and job specific bits) */
1788
1789                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1790
1791                 if (r->in.access_mask &
1792                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1793                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1794                         close_printer_handle(p, r->out.handle);
1795                         ZERO_STRUCTP(r->out.handle);
1796                         return WERR_ACCESS_DENIED;
1797                 }
1798
1799                 /* Allow admin access */
1800
1801                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1802                 {
1803                         if (!lp_ms_add_printer_wizard()) {
1804                                 close_printer_handle(p, r->out.handle);
1805                                 ZERO_STRUCTP(r->out.handle);
1806                                 return WERR_ACCESS_DENIED;
1807                         }
1808
1809                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1810                            and not a printer admin, then fail */
1811
1812                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1813                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1814                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1815                                                 p->session_info->security_token)) {
1816                                 close_printer_handle(p, r->out.handle);
1817                                 ZERO_STRUCTP(r->out.handle);
1818                                 DEBUG(3,("access DENIED as user is not root, "
1819                                         "has no printoperator privilege, "
1820                                         "not a member of the printoperator builtin group and "
1821                                         "is not in printer admin list"));
1822                                 return WERR_ACCESS_DENIED;
1823                         }
1824
1825                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1826                 }
1827                 else
1828                 {
1829                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1830                 }
1831
1832                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1833                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1834
1835                 /* We fall through to return WERR_OK */
1836                 break;
1837
1838         case SPLHND_PRINTER:
1839                 /* NT doesn't let us connect to a printer if the connecting user
1840                    doesn't have print permission.  */
1841
1842                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1843                         close_printer_handle(p, r->out.handle);
1844                         ZERO_STRUCTP(r->out.handle);
1845                         return WERR_BADFID;
1846                 }
1847
1848                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1849                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1850                 }
1851
1852                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1853
1854                 /* map an empty access mask to the minimum access mask */
1855                 if (r->in.access_mask == 0x0)
1856                         r->in.access_mask = PRINTER_ACCESS_USE;
1857
1858                 /*
1859                  * If we are not serving the printer driver for this printer,
1860                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1861                  * will keep NT clients happy  --jerry
1862                  */
1863
1864                 if (lp_use_client_driver(snum)
1865                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1866                 {
1867                         r->in.access_mask = PRINTER_ACCESS_USE;
1868                 }
1869
1870                 /* check smb.conf parameters and the the sec_desc */
1871                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1872                                                          p->mem_ctx);
1873                 if (raddr == NULL) {
1874                         return WERR_NOMEM;
1875                 }
1876
1877                 rc = get_remote_hostname(p->remote_address,
1878                                          &rhost,
1879                                          p->mem_ctx);
1880                 if (rc < 0) {
1881                         return WERR_NOMEM;
1882                 }
1883                 if (strequal(rhost, "UNKNOWN")) {
1884                         rhost = raddr;
1885                 }
1886
1887                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1888                                   rhost, raddr)) {
1889                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1890                         ZERO_STRUCTP(r->out.handle);
1891                         return WERR_ACCESS_DENIED;
1892                 }
1893
1894                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1895                                    p->session_info->security_token, snum) ||
1896                     !print_access_check(p->session_info,
1897                                         p->msg_ctx,
1898                                         snum,
1899                                         r->in.access_mask)) {
1900                         DEBUG(3, ("access DENIED for printer open\n"));
1901                         close_printer_handle(p, r->out.handle);
1902                         ZERO_STRUCTP(r->out.handle);
1903                         return WERR_ACCESS_DENIED;
1904                 }
1905
1906                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1907                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1908                         close_printer_handle(p, r->out.handle);
1909                         ZERO_STRUCTP(r->out.handle);
1910                         return WERR_ACCESS_DENIED;
1911                 }
1912
1913                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1914                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1915                 else
1916                         r->in.access_mask = PRINTER_ACCESS_USE;
1917
1918                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1919                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1920
1921                 winreg_create_printer_internal(p->mem_ctx,
1922                                       get_session_info_system(),
1923                                       p->msg_ctx,
1924                                       lp_const_servicename(snum));
1925
1926                 break;
1927
1928         default:
1929                 /* sanity check to prevent programmer error */
1930                 ZERO_STRUCTP(r->out.handle);
1931                 return WERR_BADFID;
1932         }
1933
1934         Printer->access_granted = r->in.access_mask;
1935
1936         /*
1937          * If the client sent a devmode in the OpenPrinter() call, then
1938          * save it here in case we get a job submission on this handle
1939          */
1940
1941          if ((Printer->printer_type != SPLHND_SERVER) &&
1942              r->in.devmode_ctr.devmode) {
1943                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1944                                 &Printer->devmode);
1945          }
1946
1947 #if 0   /* JERRY -- I'm doubtful this is really effective */
1948         /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1949            optimization in Windows 2000 clients  --jerry */
1950
1951         if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1952                 && (RA_WIN2K == get_remote_arch()) )
1953         {
1954                 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1955                 usleep( 500000 );
1956         }
1957 #endif
1958
1959         return WERR_OK;
1960 }
1961
1962 /****************************************************************
1963  _spoolss_ClosePrinter
1964 ****************************************************************/
1965
1966 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1967                              struct spoolss_ClosePrinter *r)
1968 {
1969         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1970
1971         if (Printer && Printer->document_started) {
1972                 struct spoolss_EndDocPrinter e;
1973
1974                 e.in.handle = r->in.handle;
1975
1976                 _spoolss_EndDocPrinter(p, &e);
1977         }
1978
1979         if (!close_printer_handle(p, r->in.handle))
1980                 return WERR_BADFID;
1981
1982         /* clear the returned printer handle.  Observed behavior
1983            from Win2k server.  Don't think this really matters.
1984            Previous code just copied the value of the closed
1985            handle.    --jerry */
1986
1987         ZERO_STRUCTP(r->out.handle);
1988
1989         return WERR_OK;
1990 }
1991
1992 /****************************************************************
1993  _spoolss_DeletePrinter
1994 ****************************************************************/
1995
1996 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1997                               struct spoolss_DeletePrinter *r)
1998 {
1999         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2000         WERROR result;
2001         int snum;
2002
2003         if (Printer && Printer->document_started) {
2004                 struct spoolss_EndDocPrinter e;
2005
2006                 e.in.handle = r->in.handle;
2007
2008                 _spoolss_EndDocPrinter(p, &e);
2009         }
2010
2011         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2012                 winreg_delete_printer_key_internal(p->mem_ctx,
2013                                           get_session_info_system(),
2014                                           p->msg_ctx,
2015                                           lp_const_servicename(snum),
2016                                           "");
2017         }
2018
2019         result = delete_printer_handle(p, r->in.handle);
2020
2021         return result;
2022 }
2023
2024 /*******************************************************************
2025  * static function to lookup the version id corresponding to an
2026  * long architecture string
2027  ******************************************************************/
2028
2029 static const struct print_architecture_table_node archi_table[]= {
2030
2031         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2032         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2033         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2034         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2035         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2036         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2037         {"Windows x64",          SPL_ARCH_X64,          3 },
2038         {NULL,                   "",            -1 }
2039 };
2040
2041 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2042                                    SPOOLSS_DRIVER_VERSION_NT35,
2043                                    SPOOLSS_DRIVER_VERSION_NT4,
2044                                    SPOOLSS_DRIVER_VERSION_200X,
2045                                    -1};
2046
2047 static int get_version_id(const char *arch)
2048 {
2049         int i;
2050
2051         for (i=0; archi_table[i].long_archi != NULL; i++)
2052         {
2053                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2054                         return (archi_table[i].version);
2055         }
2056
2057         return -1;
2058 }
2059
2060 /****************************************************************
2061  _spoolss_DeletePrinterDriver
2062 ****************************************************************/
2063
2064 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2065                                     struct spoolss_DeletePrinterDriver *r)
2066 {
2067
2068         struct spoolss_DriverInfo8 *info = NULL;
2069         int                             version;
2070         WERROR                          status;
2071         struct dcerpc_binding_handle *b;
2072         TALLOC_CTX *tmp_ctx = NULL;
2073         int i;
2074         bool found;
2075
2076         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2077            and not a printer admin, then fail */
2078
2079         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2080             !security_token_has_privilege(p->session_info->security_token,
2081                                           SEC_PRIV_PRINT_OPERATOR)) {
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         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2105                 status = winreg_get_driver(tmp_ctx, b,
2106                                            r->in.architecture, r->in.driver,
2107                                            drv_cversion[i], &info);
2108                 if (!W_ERROR_IS_OK(status)) {
2109                         DEBUG(5, ("skipping del of driver with version %d\n",
2110                                   drv_cversion[i]));
2111                         continue;
2112                 }
2113                 found = true;
2114
2115                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2116                         status = WERR_PRINTER_DRIVER_IN_USE;
2117                         goto done;
2118                 }
2119
2120                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2121                 if (!W_ERROR_IS_OK(status)) {
2122                         DEBUG(0, ("failed del of driver with version %d\n",
2123                                   drv_cversion[i]));
2124                         goto done;
2125                 }
2126         }
2127         if (found == false) {
2128                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2129                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2130         } else {
2131                 status = WERR_OK;
2132         }
2133
2134 done:
2135         talloc_free(tmp_ctx);
2136
2137         return status;
2138 }
2139
2140 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2141                                   struct pipes_struct *p,
2142                                   struct spoolss_DeletePrinterDriverEx *r,
2143                                   struct dcerpc_binding_handle *b,
2144                                   struct spoolss_DriverInfo8 *info)
2145 {
2146         WERROR status;
2147         bool delete_files;
2148
2149         if (printer_driver_in_use(mem_ctx, b, info)) {
2150                 status = WERR_PRINTER_DRIVER_IN_USE;
2151                 goto done;
2152         }
2153
2154         /*
2155          * we have a couple of cases to consider.
2156          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2157          *     then the delete should fail if **any** files overlap with
2158          *     other drivers
2159          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2160          *     non-overlapping files
2161          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2162          *     are set, then do not delete any files
2163          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2164          */
2165
2166         delete_files = r->in.delete_flags
2167                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2168
2169
2170         if (delete_files) {
2171                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2172                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2173                         status = WERR_PRINTER_DRIVER_IN_USE;
2174                         goto done;
2175                 }
2176                 /*
2177                  * printer_driver_files_in_use() has trimmed overlapping files
2178                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2179                  */
2180         }
2181
2182
2183         status = winreg_del_driver(mem_ctx, b, info, info->version);
2184         if (!W_ERROR_IS_OK(status)) {
2185                 goto done;
2186         }
2187
2188         /*
2189          * now delete any associated files if delete_files is
2190          * true. Even if this part failes, we return succes
2191          * because the driver doesn not exist any more
2192          */
2193         if (delete_files) {
2194                 delete_driver_files(p->session_info, info);
2195         }
2196
2197 done:
2198         return status;
2199 }
2200
2201 /****************************************************************
2202  _spoolss_DeletePrinterDriverEx
2203 ****************************************************************/
2204
2205 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2206                                       struct spoolss_DeletePrinterDriverEx *r)
2207 {
2208         struct spoolss_DriverInfo8 *info = NULL;
2209         WERROR                          status;
2210         struct dcerpc_binding_handle *b;
2211         TALLOC_CTX *tmp_ctx = NULL;
2212         int i;
2213         bool found;
2214
2215         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2216            and not a printer admin, then fail */
2217
2218         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2219             !security_token_has_privilege(p->session_info->security_token,
2220                                           SEC_PRIV_PRINT_OPERATOR)) {
2221                 return WERR_ACCESS_DENIED;
2222         }
2223
2224         /* check that we have a valid driver name first */
2225         if (get_version_id(r->in.architecture) == -1) {
2226                 /* this is what NT returns */
2227                 return WERR_INVALID_ENVIRONMENT;
2228         }
2229
2230         tmp_ctx = talloc_new(p->mem_ctx);
2231         if (!tmp_ctx) {
2232                 return WERR_NOMEM;
2233         }
2234
2235         status = winreg_printer_binding_handle(tmp_ctx,
2236                                                get_session_info_system(),
2237                                                p->msg_ctx,
2238                                                &b);
2239         if (!W_ERROR_IS_OK(status)) {
2240                 goto done;
2241         }
2242
2243         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2244                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2245                  && (drv_cversion[i] != r->in.version)) {
2246                         continue;
2247                 }
2248
2249                 /* check if a driver with this version exists before delete */
2250                 status = winreg_get_driver(tmp_ctx, b,
2251                                            r->in.architecture, r->in.driver,
2252                                            drv_cversion[i], &info);
2253                 if (!W_ERROR_IS_OK(status)) {
2254                         DEBUG(5, ("skipping del of driver with version %d\n",
2255                                   drv_cversion[i]));
2256                         continue;
2257                 }
2258                 found = true;
2259
2260                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2261                 if (!W_ERROR_IS_OK(status)) {
2262                         DEBUG(0, ("failed to delete driver with version %d\n",
2263                                   drv_cversion[i]));
2264                         goto done;
2265                 }
2266         }
2267         if (found == false) {
2268                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2269                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2270         } else {
2271                 status = WERR_OK;
2272         }
2273
2274 done:
2275         talloc_free(tmp_ctx);
2276         return status;
2277 }
2278
2279
2280 /********************************************************************
2281  GetPrinterData on a printer server Handle.
2282 ********************************************************************/
2283
2284 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2285                                             const char *value,
2286                                             enum winreg_Type *type,
2287                                             union spoolss_PrinterData *data)
2288 {
2289         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2290
2291         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2292                 *type = REG_DWORD;
2293                 SIVAL(&data->value, 0, 0x00);
2294                 return WERR_OK;
2295         }
2296
2297         if (!strcasecmp_m(value, "BeepEnabled")) {
2298                 *type = REG_DWORD;
2299                 SIVAL(&data->value, 0, 0x00);
2300                 return WERR_OK;
2301         }
2302
2303         if (!strcasecmp_m(value, "EventLog")) {
2304                 *type = REG_DWORD;
2305                 /* formally was 0x1b */
2306                 SIVAL(&data->value, 0, 0x00);
2307                 return WERR_OK;
2308         }
2309
2310         if (!strcasecmp_m(value, "NetPopup")) {
2311                 *type = REG_DWORD;
2312                 SIVAL(&data->value, 0, 0x00);
2313                 return WERR_OK;
2314         }
2315
2316         if (!strcasecmp_m(value, "MajorVersion")) {
2317                 *type = REG_DWORD;
2318
2319                 /* Windows NT 4.0 seems to not allow uploading of drivers
2320                    to a server that reports 0x3 as the MajorVersion.
2321                    need to investigate more how Win2k gets around this .
2322                    -- jerry */
2323
2324                 if (RA_WINNT == get_remote_arch()) {
2325                         SIVAL(&data->value, 0, 0x02);
2326                 } else {
2327                         SIVAL(&data->value, 0, 0x03);
2328                 }
2329
2330                 return WERR_OK;
2331         }
2332
2333         if (!strcasecmp_m(value, "MinorVersion")) {
2334                 *type = REG_DWORD;
2335                 SIVAL(&data->value, 0, 0x00);
2336                 return WERR_OK;
2337         }
2338
2339         /* REG_BINARY
2340          *  uint32_t size        = 0x114
2341          *  uint32_t major       = 5
2342          *  uint32_t minor       = [0|1]
2343          *  uint32_t build       = [2195|2600]
2344          *  extra unicode string = e.g. "Service Pack 3"
2345          */
2346         if (!strcasecmp_m(value, "OSVersion")) {
2347                 DATA_BLOB blob;
2348                 enum ndr_err_code ndr_err;
2349                 struct spoolss_OSVersion os;
2350
2351                 os.major                = 5;    /* Windows 2000 == 5.0 */
2352                 os.minor                = 0;
2353                 os.build                = 2195; /* build */
2354                 os.extra_string         = "";   /* leave extra string empty */
2355
2356                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2357                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2358                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2359                         return WERR_GENERAL_FAILURE;
2360                 }
2361
2362                 *type = REG_BINARY;
2363                 data->binary = blob;
2364
2365                 return WERR_OK;
2366         }
2367
2368
2369         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2370                 *type = REG_SZ;
2371
2372                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2373                 W_ERROR_HAVE_NO_MEMORY(data->string);
2374
2375                 return WERR_OK;
2376         }
2377
2378         if (!strcasecmp_m(value, "Architecture")) {
2379                 *type = REG_SZ;
2380                 data->string = talloc_strdup(mem_ctx,
2381                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2382                 W_ERROR_HAVE_NO_MEMORY(data->string);
2383
2384                 return WERR_OK;
2385         }
2386
2387         if (!strcasecmp_m(value, "DsPresent")) {
2388                 *type = REG_DWORD;
2389
2390                 /* only show the publish check box if we are a
2391                    member of a AD domain */
2392
2393                 if (lp_security() == SEC_ADS) {
2394                         SIVAL(&data->value, 0, 0x01);
2395                 } else {
2396                         SIVAL(&data->value, 0, 0x00);
2397                 }
2398                 return WERR_OK;
2399         }
2400
2401         if (!strcasecmp_m(value, "DNSMachineName")) {
2402                 const char *hostname = get_mydnsfullname();
2403
2404                 if (!hostname) {
2405                         return WERR_BADFILE;
2406                 }
2407
2408                 *type = REG_SZ;
2409                 data->string = talloc_strdup(mem_ctx, hostname);
2410                 W_ERROR_HAVE_NO_MEMORY(data->string);
2411
2412                 return WERR_OK;
2413         }
2414
2415         *type = REG_NONE;
2416
2417         return WERR_INVALID_PARAM;
2418 }
2419
2420 /****************************************************************
2421  _spoolss_GetPrinterData
2422 ****************************************************************/
2423
2424 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2425                                struct spoolss_GetPrinterData *r)
2426 {
2427         struct spoolss_GetPrinterDataEx r2;
2428
2429         r2.in.handle            = r->in.handle;
2430         r2.in.key_name          = "PrinterDriverData";
2431         r2.in.value_name        = r->in.value_name;
2432         r2.in.offered           = r->in.offered;
2433         r2.out.type             = r->out.type;
2434         r2.out.data             = r->out.data;
2435         r2.out.needed           = r->out.needed;
2436
2437         return _spoolss_GetPrinterDataEx(p, &r2);
2438 }
2439
2440 /*********************************************************
2441  Connect to the client machine.
2442 **********************************************************/
2443
2444 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2445                         struct sockaddr_storage *client_ss, const char *remote_machine)
2446 {
2447         NTSTATUS ret;
2448         struct cli_state *the_cli;
2449         struct sockaddr_storage rm_addr;
2450         char addr[INET6_ADDRSTRLEN];
2451
2452         if ( is_zero_addr(client_ss) ) {
2453                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2454                         remote_machine));
2455                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2456                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2457                         return false;
2458                 }
2459                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2460         } else {
2461                 rm_addr = *client_ss;
2462                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2463                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2464                         addr));
2465         }
2466
2467         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2468                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2469                         addr));
2470                 return false;
2471         }
2472
2473         /* setup the connection */
2474         ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2475                 &rm_addr, 0, "IPC$", "IPC",
2476                 "", /* username */
2477                 "", /* domain */
2478                 "", /* password */
2479                 0, lp_client_signing());
2480
2481         if ( !NT_STATUS_IS_OK( ret ) ) {
2482                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2483                         remote_machine ));
2484                 return false;
2485         }
2486
2487         if ( smbXcli_conn_protocol(the_cli->conn) != PROTOCOL_NT1 ) {
2488                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2489                 cli_shutdown(the_cli);
2490                 return false;
2491         }
2492
2493         /*
2494          * Ok - we have an anonymous connection to the IPC$ share.
2495          * Now start the NT Domain stuff :-).
2496          */
2497
2498         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2499         if (!NT_STATUS_IS_OK(ret)) {
2500                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2501                         remote_machine, nt_errstr(ret)));
2502                 cli_shutdown(the_cli);
2503                 return false;
2504         }
2505
2506         return true;
2507 }
2508
2509 /***************************************************************************
2510  Connect to the client.
2511 ****************************************************************************/
2512
2513 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2514                                         uint32_t localprinter,
2515                                         enum winreg_Type type,
2516                                         struct policy_handle *handle,
2517                                         struct notify_back_channel **_chan,
2518                                         struct sockaddr_storage *client_ss,
2519                                         struct messaging_context *msg_ctx)
2520 {
2521         WERROR result;
2522         NTSTATUS status;
2523         struct notify_back_channel *chan;
2524
2525         for (chan = back_channels; chan; chan = chan->next) {
2526                 if (memcmp(&chan->client_address, client_ss,
2527                            sizeof(struct sockaddr_storage)) == 0) {
2528                         break;
2529                 }
2530         }
2531
2532         /*
2533          * If it's the first connection, contact the client
2534          * and connect to the IPC$ share anonymously
2535          */
2536         if (!chan) {
2537                 fstring unix_printer;
2538
2539                 /* the +2 is to strip the leading 2 backslashs */
2540                 fstrcpy(unix_printer, printer + 2);
2541
2542                 chan = talloc_zero(NULL, struct notify_back_channel);
2543                 if (!chan) {
2544                         return false;
2545                 }
2546                 chan->client_address = *client_ss;
2547
2548                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2549                         TALLOC_FREE(chan);
2550                         return false;
2551                 }
2552
2553                 DLIST_ADD(back_channels, chan);
2554
2555                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2556                                    receive_notify2_message_list);
2557         }
2558
2559         if (chan->cli_pipe == NULL ||
2560             chan->cli_pipe->binding_handle == NULL) {
2561                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2562                         "NULL %s for printer %s\n",
2563                         chan->cli_pipe == NULL ?
2564                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2565                         printer));
2566                 return false;
2567         }
2568
2569         /*
2570          * Tell the specific printing tdb we want messages for this printer
2571          * by registering our PID.
2572          */
2573
2574         if (!print_notify_register_pid(snum)) {
2575                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2576                           printer));
2577         }
2578
2579         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2580                                                  talloc_tos(),
2581                                                  printer,
2582                                                  localprinter,
2583                                                  type,
2584                                                  0,
2585                                                  NULL,
2586                                                  handle,
2587                                                  &result);
2588         if (!NT_STATUS_IS_OK(status)) {
2589                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2590                 result = ntstatus_to_werror(status);
2591         } else if (!W_ERROR_IS_OK(result)) {
2592                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2593         }
2594
2595         chan->active_connections++;
2596         *_chan = chan;
2597
2598         return (W_ERROR_IS_OK(result));
2599 }
2600
2601 /****************************************************************
2602  ****************************************************************/
2603
2604 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2605                                                              const struct spoolss_NotifyOption *r)
2606 {
2607         struct spoolss_NotifyOption *option;
2608         uint32_t i,k;
2609
2610         if (!r) {
2611                 return NULL;
2612         }
2613
2614         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2615         if (!option) {
2616                 return NULL;
2617         }
2618
2619         *option = *r;
2620
2621         if (!option->count) {
2622                 return option;
2623         }
2624
2625         option->types = talloc_zero_array(option,
2626                 struct spoolss_NotifyOptionType, option->count);
2627         if (!option->types) {
2628                 talloc_free(option);
2629                 return NULL;
2630         }
2631
2632         for (i=0; i < option->count; i++) {
2633                 option->types[i] = r->types[i];
2634
2635                 if (option->types[i].count) {
2636                         option->types[i].fields = talloc_zero_array(option,
2637                                 union spoolss_Field, option->types[i].count);
2638                         if (!option->types[i].fields) {
2639                                 talloc_free(option);
2640                                 return NULL;
2641                         }
2642                         for (k=0; k<option->types[i].count; k++) {
2643                                 option->types[i].fields[k] =
2644                                         r->types[i].fields[k];
2645                         }
2646                 }
2647         }
2648
2649         return option;
2650 }
2651
2652 /****************************************************************
2653  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2654  *
2655  * before replying OK: status=0 a rpc call is made to the workstation
2656  * asking ReplyOpenPrinter
2657  *
2658  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2659  * called from api_spoolss_rffpcnex
2660 ****************************************************************/
2661
2662 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2663                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2664 {
2665         int snum = -1;
2666         struct spoolss_NotifyOption *option = r->in.notify_options;
2667         struct sockaddr_storage client_ss;
2668         ssize_t client_len;
2669
2670         /* store the notify value in the printer struct */
2671
2672         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2673
2674         if (!Printer) {
2675                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2676                         "Invalid handle (%s:%u:%u).\n",
2677                         OUR_HANDLE(r->in.handle)));
2678                 return WERR_BADFID;
2679         }
2680
2681         Printer->notify.flags           = r->in.flags;
2682         Printer->notify.options         = r->in.options;
2683         Printer->notify.printerlocal    = r->in.printer_local;
2684         Printer->notify.msg_ctx         = p->msg_ctx;
2685
2686         TALLOC_FREE(Printer->notify.option);
2687         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2688
2689         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2690
2691         /* Connect to the client machine and send a ReplyOpenPrinter */
2692
2693         if ( Printer->printer_type == SPLHND_SERVER)
2694                 snum = -1;
2695         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2696                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2697                 return WERR_BADFID;
2698
2699         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2700                   "remote_address is %s\n",
2701                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2702
2703         if (!lp_print_notify_backchannel(snum)) {
2704                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2705                         "backchannel disabled\n"));
2706                 return WERR_SERVER_UNAVAILABLE;
2707         }
2708
2709         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2710                                                   (struct sockaddr *) &client_ss,
2711                                                   sizeof(struct sockaddr_storage));
2712         if (client_len < 0) {
2713                 return WERR_NOMEM;
2714         }
2715
2716         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2717                                         Printer->notify.printerlocal, REG_SZ,
2718                                         &Printer->notify.cli_hnd,
2719                                         &Printer->notify.cli_chan,
2720                                         &client_ss, p->msg_ctx)) {
2721                 return WERR_SERVER_UNAVAILABLE;
2722         }
2723
2724         return WERR_OK;
2725 }
2726
2727 /*******************************************************************
2728  * fill a notify_info_data with the servername
2729  ********************************************************************/
2730
2731 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2732                                        int snum,
2733                                        struct spoolss_Notify *data,
2734                                        print_queue_struct *queue,
2735                                        struct spoolss_PrinterInfo2 *pinfo2,
2736                                        TALLOC_CTX *mem_ctx)
2737 {
2738         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2739 }
2740
2741 /*******************************************************************
2742  * fill a notify_info_data with the printername (not including the servername).
2743  ********************************************************************/
2744
2745 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2746                                         int snum,
2747                                         struct spoolss_Notify *data,
2748                                         print_queue_struct *queue,
2749                                         struct spoolss_PrinterInfo2 *pinfo2,
2750                                         TALLOC_CTX *mem_ctx)
2751 {
2752         /* the notify name should not contain the \\server\ part */
2753         const char *p = strrchr(pinfo2->printername, '\\');
2754
2755         if (!p) {
2756                 p = pinfo2->printername;
2757         } else {
2758                 p++;
2759         }
2760
2761         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2762 }
2763
2764 /*******************************************************************
2765  * fill a notify_info_data with the servicename
2766  ********************************************************************/
2767
2768 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2769                                       int snum,
2770                                       struct spoolss_Notify *data,
2771                                       print_queue_struct *queue,
2772                                       struct spoolss_PrinterInfo2 *pinfo2,
2773                                       TALLOC_CTX *mem_ctx)
2774 {
2775         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2776 }
2777
2778 /*******************************************************************
2779  * fill a notify_info_data with the port name
2780  ********************************************************************/
2781
2782 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2783                                      int snum,
2784                                      struct spoolss_Notify *data,
2785                                      print_queue_struct *queue,
2786                                      struct spoolss_PrinterInfo2 *pinfo2,
2787                                      TALLOC_CTX *mem_ctx)
2788 {
2789         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2790 }
2791
2792 /*******************************************************************
2793  * fill a notify_info_data with the printername
2794  * but it doesn't exist, have to see what to do
2795  ********************************************************************/
2796
2797 static void spoolss_notify_driver_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->drivername);
2805 }
2806
2807 /*******************************************************************
2808  * fill a notify_info_data with the comment
2809  ********************************************************************/
2810
2811 static void spoolss_notify_comment(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         const char *p;
2819
2820         if (*pinfo2->comment == '\0') {
2821                 p = lp_comment(snum);
2822         } else {
2823                 p = pinfo2->comment;
2824         }
2825
2826         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2827 }
2828
2829 /*******************************************************************
2830  * fill a notify_info_data with the comment
2831  * location = "Room 1, floor 2, building 3"
2832  ********************************************************************/
2833
2834 static void spoolss_notify_location(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         const char *loc = pinfo2->location;
2842         NTSTATUS status;
2843
2844         status = printer_list_get_printer(mem_ctx,
2845                                           pinfo2->sharename,
2846                                           NULL,
2847                                           &loc,
2848                                           NULL);
2849         if (NT_STATUS_IS_OK(status)) {
2850                 if (loc == NULL) {
2851                         loc = pinfo2->location;
2852                 }
2853         }
2854
2855         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2856 }
2857
2858 /*******************************************************************
2859  * fill a notify_info_data with the device mode
2860  * jfm:xxxx don't to it for know but that's a real problem !!!
2861  ********************************************************************/
2862
2863 static void spoolss_notify_devmode(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         /* for a dummy implementation we have to zero the fields */
2871         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2872 }
2873
2874 /*******************************************************************
2875  * fill a notify_info_data with the separator file name
2876  ********************************************************************/
2877
2878 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2879                                    int snum,
2880                                    struct spoolss_Notify *data,
2881                                    print_queue_struct *queue,
2882                                    struct spoolss_PrinterInfo2 *pinfo2,
2883                                    TALLOC_CTX *mem_ctx)
2884 {
2885         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2886 }
2887
2888 /*******************************************************************
2889  * fill a notify_info_data with the print processor
2890  * jfm:xxxx return always winprint to indicate we don't do anything to it
2891  ********************************************************************/
2892
2893 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2894                                            int snum,
2895                                            struct spoolss_Notify *data,
2896                                            print_queue_struct *queue,
2897                                            struct spoolss_PrinterInfo2 *pinfo2,
2898                                            TALLOC_CTX *mem_ctx)
2899 {
2900         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2901 }
2902
2903 /*******************************************************************
2904  * fill a notify_info_data with the print processor options
2905  * jfm:xxxx send an empty string
2906  ********************************************************************/
2907
2908 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2909                                       int snum,
2910                                       struct spoolss_Notify *data,
2911                                       print_queue_struct *queue,
2912                                       struct spoolss_PrinterInfo2 *pinfo2,
2913                                       TALLOC_CTX *mem_ctx)
2914 {
2915         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2916 }
2917
2918 /*******************************************************************
2919  * fill a notify_info_data with the data type
2920  * jfm:xxxx always send RAW as data type
2921  ********************************************************************/
2922
2923 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2924                                     int snum,
2925                                     struct spoolss_Notify *data,
2926                                     print_queue_struct *queue,
2927                                     struct spoolss_PrinterInfo2 *pinfo2,
2928                                     TALLOC_CTX *mem_ctx)
2929 {
2930         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2931 }
2932
2933 /*******************************************************************
2934  * fill a notify_info_data with the security descriptor
2935  * jfm:xxxx send an null pointer to say no security desc
2936  * have to implement security before !
2937  ********************************************************************/
2938
2939 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2940                                          int snum,
2941                                          struct spoolss_Notify *data,
2942                                          print_queue_struct *queue,
2943                                          struct spoolss_PrinterInfo2 *pinfo2,
2944                                          TALLOC_CTX *mem_ctx)
2945 {
2946         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2947 }
2948
2949 /*******************************************************************
2950  * fill a notify_info_data with the attributes
2951  * jfm:xxxx a samba printer is always shared
2952  ********************************************************************/
2953
2954 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2955                                       int snum,
2956                                       struct spoolss_Notify *data,
2957                                       print_queue_struct *queue,
2958                                       struct spoolss_PrinterInfo2 *pinfo2,
2959                                       TALLOC_CTX *mem_ctx)
2960 {
2961         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2962 }
2963
2964 /*******************************************************************
2965  * fill a notify_info_data with the priority
2966  ********************************************************************/
2967
2968 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2969                                     int snum,
2970                                     struct spoolss_Notify *data,
2971                                     print_queue_struct *queue,
2972                                     struct spoolss_PrinterInfo2 *pinfo2,
2973                                     TALLOC_CTX *mem_ctx)
2974 {
2975         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2976 }
2977
2978 /*******************************************************************
2979  * fill a notify_info_data with the default priority
2980  ********************************************************************/
2981
2982 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2983                                             int snum,
2984                                             struct spoolss_Notify *data,
2985                                             print_queue_struct *queue,
2986                                             struct spoolss_PrinterInfo2 *pinfo2,
2987                                             TALLOC_CTX *mem_ctx)
2988 {
2989         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2990 }
2991
2992 /*******************************************************************
2993  * fill a notify_info_data with the start time
2994  ********************************************************************/
2995
2996 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2997                                       int snum,
2998                                       struct spoolss_Notify *data,
2999                                       print_queue_struct *queue,
3000                                       struct spoolss_PrinterInfo2 *pinfo2,
3001                                       TALLOC_CTX *mem_ctx)
3002 {
3003         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3004 }
3005
3006 /*******************************************************************
3007  * fill a notify_info_data with the until time
3008  ********************************************************************/
3009
3010 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3011                                       int snum,
3012                                       struct spoolss_Notify *data,
3013                                       print_queue_struct *queue,
3014                                       struct spoolss_PrinterInfo2 *pinfo2,
3015                                       TALLOC_CTX *mem_ctx)
3016 {
3017         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3018 }
3019
3020 /*******************************************************************
3021  * fill a notify_info_data with the status
3022  ********************************************************************/
3023
3024 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3025                                   int snum,
3026                                   struct spoolss_Notify *data,
3027                                   print_queue_struct *queue,
3028                                   struct spoolss_PrinterInfo2 *pinfo2,
3029                                   TALLOC_CTX *mem_ctx)
3030 {
3031         print_status_struct status;
3032
3033         print_queue_length(msg_ctx, snum, &status);
3034         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3035 }
3036
3037 /*******************************************************************
3038  * fill a notify_info_data with the number of jobs queued
3039  ********************************************************************/
3040
3041 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3042                                  int snum,
3043                                  struct spoolss_Notify *data,
3044                                  print_queue_struct *queue,
3045                                  struct spoolss_PrinterInfo2 *pinfo2,
3046                                  TALLOC_CTX *mem_ctx)
3047 {
3048         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3049                 data, print_queue_length(msg_ctx, snum, NULL));
3050 }
3051
3052 /*******************************************************************
3053  * fill a notify_info_data with the average ppm
3054  ********************************************************************/
3055
3056 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3057                                        int snum,
3058                                        struct spoolss_Notify *data,
3059                                        print_queue_struct *queue,
3060                                        struct spoolss_PrinterInfo2 *pinfo2,
3061                                        TALLOC_CTX *mem_ctx)
3062 {
3063         /* always respond 8 pages per minutes */
3064         /* a little hard ! */
3065         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3066 }
3067
3068 /*******************************************************************
3069  * fill a notify_info_data with username
3070  ********************************************************************/
3071
3072 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3073                                     int snum,
3074                                     struct spoolss_Notify *data,
3075                                     print_queue_struct *queue,
3076                                     struct spoolss_PrinterInfo2 *pinfo2,
3077                                     TALLOC_CTX *mem_ctx)
3078 {
3079         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3080 }
3081
3082 /*******************************************************************
3083  * fill a notify_info_data with job status
3084  ********************************************************************/
3085
3086 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3087                                       int snum,
3088                                       struct spoolss_Notify *data,
3089                                       print_queue_struct *queue,
3090                                       struct spoolss_PrinterInfo2 *pinfo2,
3091                                       TALLOC_CTX *mem_ctx)
3092 {
3093         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3094 }
3095
3096 /*******************************************************************
3097  * fill a notify_info_data with job name
3098  ********************************************************************/
3099
3100 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3101                                     int snum,
3102                                     struct spoolss_Notify *data,
3103                                     print_queue_struct *queue,
3104                                     struct spoolss_PrinterInfo2 *pinfo2,
3105                                     TALLOC_CTX *mem_ctx)
3106 {
3107         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3108 }
3109
3110 /*******************************************************************
3111  * fill a notify_info_data with job status
3112  ********************************************************************/
3113
3114 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3115                                              int snum,
3116                                              struct spoolss_Notify *data,
3117                                              print_queue_struct *queue,
3118                                              struct spoolss_PrinterInfo2 *pinfo2,
3119                                              TALLOC_CTX *mem_ctx)
3120 {
3121         /*
3122          * Now we're returning job status codes we just return a "" here. JRA.
3123          */
3124
3125         const char *p = "";
3126
3127 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3128         p = "unknown";
3129
3130         switch (queue->status) {
3131         case LPQ_QUEUED:
3132                 p = "Queued";
3133                 break;
3134         case LPQ_PAUSED:
3135                 p = "";    /* NT provides the paused string */
3136                 break;
3137         case LPQ_SPOOLING:
3138                 p = "Spooling";
3139                 break;
3140         case LPQ_PRINTING:
3141                 p = "Printing";
3142                 break;
3143         }
3144 #endif /* NO LONGER NEEDED. */
3145
3146         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3147 }
3148
3149 /*******************************************************************
3150  * fill a notify_info_data with job time
3151  ********************************************************************/
3152
3153 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3154                                     int snum,
3155                                     struct spoolss_Notify *data,
3156                                     print_queue_struct *queue,
3157                                     struct spoolss_PrinterInfo2 *pinfo2,
3158                                     TALLOC_CTX *mem_ctx)
3159 {
3160         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3161 }
3162
3163 /*******************************************************************
3164  * fill a notify_info_data with job size
3165  ********************************************************************/
3166
3167 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3168                                     int snum,
3169                                     struct spoolss_Notify *data,
3170                                     print_queue_struct *queue,
3171                                     struct spoolss_PrinterInfo2 *pinfo2,
3172                                     TALLOC_CTX *mem_ctx)
3173 {
3174         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3175 }
3176
3177 /*******************************************************************
3178  * fill a notify_info_data with page info
3179  ********************************************************************/
3180 static void spoolss_notify_total_pages(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         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3188 }
3189
3190 /*******************************************************************
3191  * fill a notify_info_data with pages printed info.
3192  ********************************************************************/
3193 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3194                                          int snum,
3195                                 struct spoolss_Notify *data,
3196                                 print_queue_struct *queue,
3197                                 struct spoolss_PrinterInfo2 *pinfo2,
3198                                 TALLOC_CTX *mem_ctx)
3199 {
3200         /* Add code when back-end tracks this */
3201         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3202 }
3203
3204 /*******************************************************************
3205  Fill a notify_info_data with job position.
3206  ********************************************************************/
3207
3208 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3209                                         int snum,
3210                                         struct spoolss_Notify *data,
3211                                         print_queue_struct *queue,
3212                                         struct spoolss_PrinterInfo2 *pinfo2,
3213                                         TALLOC_CTX *mem_ctx)
3214 {
3215         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3216 }
3217
3218 /*******************************************************************
3219  Fill a notify_info_data with submitted time.
3220  ********************************************************************/
3221
3222 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3223                                           int snum,
3224                                           struct spoolss_Notify *data,
3225                                           print_queue_struct *queue,
3226                                           struct spoolss_PrinterInfo2 *pinfo2,
3227                                           TALLOC_CTX *mem_ctx)
3228 {
3229         data->data.string.string = NULL;
3230         data->data.string.size = 0;
3231
3232         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3233                                &data->data.string.string,
3234                                &data->data.string.size);
3235
3236 }
3237
3238 struct s_notify_info_data_table
3239 {
3240         enum spoolss_NotifyType type;
3241         uint16_t field;
3242         const char *name;
3243         enum spoolss_NotifyTable variable_type;
3244         void (*fn) (struct messaging_context *msg_ctx,
3245                     int snum, struct spoolss_Notify *data,
3246                     print_queue_struct *queue,
3247                     struct spoolss_PrinterInfo2 *pinfo2,
3248                     TALLOC_CTX *mem_ctx);
3249 };
3250
3251 /* A table describing the various print notification constants and
3252    whether the notification data is a pointer to a variable sized
3253    buffer, a one value uint32_t or a two value uint32_t. */
3254
3255 static const struct s_notify_info_data_table notify_info_data_table[] =
3256 {
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3283 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3284 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3285 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3286 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3287 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3288 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3289 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3290 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3291 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3292 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3293 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3294 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3295 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3296 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3301 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3302 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3304 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3305 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3306 };
3307
3308 /*******************************************************************
3309  Return the variable_type of info_data structure.
3310 ********************************************************************/
3311
3312 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3313                                                                   uint16_t field)
3314 {
3315         int i=0;
3316
3317         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3318                 if ( (notify_info_data_table[i].type == type) &&
3319                      (notify_info_data_table[i].field == field) ) {
3320                         return notify_info_data_table[i].variable_type;
3321                 }
3322         }
3323
3324         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3325
3326         return (enum spoolss_NotifyTable) 0;
3327 }
3328
3329 /****************************************************************************
3330 ****************************************************************************/
3331
3332 static bool search_notify(enum spoolss_NotifyType type,
3333                           uint16_t field,
3334                           int *value)
3335 {
3336         int i;
3337
3338         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3339                 if (notify_info_data_table[i].type == type &&
3340                     notify_info_data_table[i].field == field &&
3341                     notify_info_data_table[i].fn != NULL) {
3342                         *value = i;
3343                         return true;
3344                 }
3345         }
3346
3347         return false;
3348 }
3349
3350 /****************************************************************************
3351 ****************************************************************************/
3352
3353 static void construct_info_data(struct spoolss_Notify *info_data,
3354                                 enum spoolss_NotifyType type,
3355                                 uint16_t field, int id)
3356 {
3357         info_data->type                 = type;
3358         info_data->field.field          = field;
3359         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3360         info_data->job_id               = id;
3361 }
3362
3363 /*******************************************************************
3364  *
3365  * fill a notify_info struct with info asked
3366  *
3367  ********************************************************************/
3368
3369 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3370                                           struct printer_handle *print_hnd,
3371                                           struct spoolss_NotifyInfo *info,
3372                                           struct spoolss_PrinterInfo2 *pinfo2,
3373                                           int snum,
3374                                           const struct spoolss_NotifyOptionType *option_type,
3375                                           uint32_t id,
3376                                           TALLOC_CTX *mem_ctx)
3377 {
3378         int field_num,j;
3379         enum spoolss_NotifyType type;
3380         uint16_t field;
3381
3382         struct spoolss_Notify *current_data;
3383
3384         type = option_type->type;
3385
3386         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3387                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3388                 option_type->count, lp_servicename(snum)));
3389
3390         for(field_num=0; field_num < option_type->count; field_num++) {
3391                 field = option_type->fields[field_num].field;
3392
3393                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3394
3395                 if (!search_notify(type, field, &j) )
3396                         continue;
3397
3398                 info->notifies = talloc_realloc(info, info->notifies,
3399                                                       struct spoolss_Notify,
3400                                                       info->count + 1);
3401                 if (info->notifies == NULL) {
3402                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3403                         return false;
3404                 }
3405
3406                 current_data = &info->notifies[info->count];
3407
3408                 construct_info_data(current_data, type, field, id);
3409
3410                 DEBUG(10, ("construct_notify_printer_info: "
3411                            "calling [%s]  snum=%d  printername=[%s])\n",
3412                            notify_info_data_table[j].name, snum,
3413                            pinfo2->printername));
3414
3415                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3416                                              NULL, pinfo2, mem_ctx);
3417
3418                 info->count++;
3419         }
3420
3421         return true;
3422 }
3423
3424 /*******************************************************************
3425  *
3426  * fill a notify_info struct with info asked
3427  *
3428  ********************************************************************/
3429
3430 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3431                                        print_queue_struct *queue,
3432                                        struct spoolss_NotifyInfo *info,
3433                                        struct spoolss_PrinterInfo2 *pinfo2,
3434                                        int snum,
3435                                        const struct spoolss_NotifyOptionType *option_type,
3436                                        uint32_t id,
3437                                        TALLOC_CTX *mem_ctx)
3438 {
3439         int field_num,j;
3440         enum spoolss_NotifyType type;
3441         uint16_t field;
3442         struct spoolss_Notify *current_data;
3443
3444         DEBUG(4,("construct_notify_jobs_info\n"));
3445
3446         type = option_type->type;
3447
3448         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3449                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3450                 option_type->count));
3451
3452         for(field_num=0; field_num<option_type->count; field_num++) {
3453                 field = option_type->fields[field_num].field;
3454
3455                 if (!search_notify(type, field, &j) )
3456                         continue;
3457
3458                 info->notifies = talloc_realloc(info, info->notifies,
3459                                                       struct spoolss_Notify,
3460                                                       info->count + 1);
3461                 if (info->notifies == NULL) {
3462                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3463                         return false;
3464                 }
3465
3466                 current_data=&(info->notifies[info->count]);
3467
3468                 construct_info_data(current_data, type, field, id);
3469                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3470                                              queue, pinfo2, mem_ctx);
3471                 info->count++;
3472         }
3473
3474         return true;
3475 }
3476
3477 /*
3478  * JFM: The enumeration is not that simple, it's even non obvious.
3479  *
3480  * let's take an example: I want to monitor the PRINTER SERVER for
3481  * the printer's name and the number of jobs currently queued.
3482  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3483  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3484  *
3485  * I have 3 printers on the back of my server.
3486  *
3487  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3488  * structures.
3489  *   Number     Data                    Id
3490  *      1       printer 1 name          1
3491  *      2       printer 1 cjob          1
3492  *      3       printer 2 name          2
3493  *      4       printer 2 cjob          2
3494  *      5       printer 3 name          3
3495  *      6       printer 3 name          3
3496  *
3497  * that's the print server case, the printer case is even worse.
3498  */
3499
3500 /*******************************************************************
3501  *
3502  * enumerate all printers on the printserver
3503  * fill a notify_info struct with info asked
3504  *
3505  ********************************************************************/
3506
3507 static WERROR printserver_notify_info(struct pipes_struct *p,
3508                                       struct policy_handle *hnd,
3509                                       struct spoolss_NotifyInfo *info,
3510                                       TALLOC_CTX *mem_ctx)
3511 {
3512         int snum;
3513         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3514         int n_services=lp_numservices();
3515         int i;
3516         struct spoolss_NotifyOption *option;
3517         struct spoolss_NotifyOptionType option_type;
3518         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3519         WERROR result;
3520
3521         DEBUG(4,("printserver_notify_info\n"));
3522
3523         if (!Printer)
3524                 return WERR_BADFID;
3525
3526         option = Printer->notify.option;
3527
3528         info->version   = 2;
3529         info->notifies  = NULL;
3530         info->count     = 0;
3531
3532         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3533            sending a ffpcn() request first */
3534
3535         if ( !option )
3536                 return WERR_BADFID;
3537
3538         for (i=0; i<option->count; i++) {
3539                 option_type = option->types[i];
3540
3541                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3542                         continue;
3543
3544                 for (snum = 0; snum < n_services; snum++) {
3545                         if (!lp_browseable(snum) ||
3546                             !lp_snum_ok(snum) ||
3547                             !lp_print_ok(snum)) {
3548                                 continue; /* skip */
3549                         }
3550
3551                         /* Maybe we should use the SYSTEM session_info here... */
3552                         result = winreg_get_printer_internal(mem_ctx,
3553                                                     get_session_info_system(),
3554                                                     p->msg_ctx,
3555                                                     lp_servicename(snum),
3556                                                     &pinfo2);
3557                         if (!W_ERROR_IS_OK(result)) {
3558                                 DEBUG(4, ("printserver_notify_info: "
3559                                           "Failed to get printer [%s]\n",
3560                                           lp_servicename(snum)));
3561                                 continue;
3562                         }
3563
3564
3565                         construct_notify_printer_info(p->msg_ctx,
3566                                                       Printer, info,
3567                                                       pinfo2, snum,
3568                                                       &option_type, snum,
3569                                                       mem_ctx);
3570
3571                         TALLOC_FREE(pinfo2);
3572                 }
3573         }
3574
3575 #if 0
3576         /*
3577          * Debugging information, don't delete.
3578          */
3579
3580         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3581         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3582         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3583
3584         for (i=0; i<info->count; i++) {
3585                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3586                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3587                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3588         }
3589 #endif
3590
3591         return WERR_OK;
3592 }
3593
3594 /*******************************************************************
3595  *
3596  * fill a notify_info struct with info asked
3597  *
3598  ********************************************************************/
3599
3600 static WERROR printer_notify_info(struct pipes_struct *p,
3601                                   struct policy_handle *hnd,
3602                                   struct spoolss_NotifyInfo *info,
3603                                   TALLOC_CTX *mem_ctx)
3604 {
3605         int snum;
3606         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3607         int i;
3608         uint32_t id;
3609         struct spoolss_NotifyOption *option;
3610         struct spoolss_NotifyOptionType option_type;
3611         int count,j;
3612         print_queue_struct *queue=NULL;
3613         print_status_struct status;
3614         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3615         WERROR result;
3616
3617         DEBUG(4,("printer_notify_info\n"));
3618
3619         if (!Printer)
3620                 return WERR_BADFID;
3621
3622         option = Printer->notify.option;
3623         id = 0x0;
3624
3625         info->version   = 2;
3626         info->notifies  = NULL;
3627         info->count     = 0;
3628
3629         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3630            sending a ffpcn() request first */
3631
3632         if ( !option )
3633                 return WERR_BADFID;
3634
3635         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3636                 return WERR_BADFID;
3637         }
3638
3639         /* Maybe we should use the SYSTEM session_info here... */
3640         result = winreg_get_printer_internal(mem_ctx,
3641                                     get_session_info_system(),
3642                                     p->msg_ctx,
3643                                     lp_servicename(snum), &pinfo2);
3644         if (!W_ERROR_IS_OK(result)) {
3645                 return WERR_BADFID;
3646         }
3647
3648         /*
3649          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3650          * correct servername.
3651          */
3652         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3653         if (pinfo2->servername == NULL) {
3654                 return WERR_NOMEM;
3655         }
3656
3657         for (i=0; i<option->count; i++) {
3658                 option_type = option->types[i];
3659
3660                 switch (option_type.type) {
3661                 case PRINTER_NOTIFY_TYPE:
3662                         if (construct_notify_printer_info(p->msg_ctx,
3663                                                           Printer, info,
3664                                                           pinfo2, snum,
3665                                                           &option_type, id,
3666                                                           mem_ctx)) {
3667                                 id--;
3668                         }
3669                         break;
3670
3671                 case JOB_NOTIFY_TYPE:
3672
3673                         count = print_queue_status(p->msg_ctx, snum, &queue,
3674                                                    &status);
3675
3676                         for (j=0; j<count; j++) {
3677                                 construct_notify_jobs_info(p->msg_ctx,
3678                                                            &queue[j], info,
3679                                                            pinfo2, snum,
3680                                                            &option_type,
3681                                                            queue[j].sysjob,
3682                                                            mem_ctx);
3683                         }
3684
3685                         SAFE_FREE(queue);
3686                         break;
3687                 }
3688         }
3689
3690         /*
3691          * Debugging information, don't delete.
3692          */
3693         /*
3694         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3695         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3696         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3697
3698         for (i=0; i<info->count; i++) {
3699                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3700                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3701                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3702         }
3703         */
3704
3705         talloc_free(pinfo2);
3706         return WERR_OK;
3707 }
3708
3709 /****************************************************************
3710  _spoolss_RouterRefreshPrinterChangeNotify
3711 ****************************************************************/
3712
3713 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3714                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3715 {
3716         struct spoolss_NotifyInfo *info;
3717
3718         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3719         WERROR result = WERR_BADFID;
3720
3721         /* we always have a spoolss_NotifyInfo struct */
3722         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3723         if (!info) {
3724                 result = WERR_NOMEM;
3725                 goto done;
3726         }
3727
3728         *r->out.info = info;
3729
3730         if (!Printer) {
3731                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3732                         "Invalid handle (%s:%u:%u).\n",
3733                         OUR_HANDLE(r->in.handle)));
3734                 goto done;
3735         }
3736
3737         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3738
3739         /*
3740          *      We are now using the change value, and
3741          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3742          *      I don't have a global notification system, I'm sending back all the
3743          *      information even when _NOTHING_ has changed.
3744          */
3745
3746         /* We need to keep track of the change value to send back in
3747            RRPCN replies otherwise our updates are ignored. */
3748
3749         Printer->notify.fnpcn = true;
3750
3751         if (Printer->notify.cli_chan != NULL &&
3752             Printer->notify.cli_chan->active_connections > 0) {
3753                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3754                         "Saving change value in request [%x]\n",
3755                         r->in.change_low));
3756                 Printer->notify.change = r->in.change_low;
3757         }
3758
3759         /* just ignore the spoolss_NotifyOption */
3760
3761         switch (Printer->printer_type) {
3762                 case SPLHND_SERVER:
3763                         result = printserver_notify_info(p, r->in.handle,
3764                                                          info, p->mem_ctx);
3765                         break;
3766
3767                 case SPLHND_PRINTER:
3768                         result = printer_notify_info(p, r->in.handle,
3769                                                      info, p->mem_ctx);
3770                         break;
3771         }
3772
3773         Printer->notify.fnpcn = false;
3774
3775 done:
3776         return result;
3777 }
3778
3779 /********************************************************************
3780  ********************************************************************/
3781
3782 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3783                                  const char *servername,
3784                                  const char *printername,
3785                                  const char **printername_p)
3786 {
3787         /* FIXME: add lp_force_printername() */
3788
3789         if (servername == NULL) {
3790                 *printername_p = talloc_strdup(mem_ctx, printername);
3791                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3792                 return WERR_OK;
3793         }
3794
3795         if (servername[0] == '\\' && servername[1] == '\\') {
3796                 servername += 2;
3797         }
3798
3799         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3800         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3801
3802         return WERR_OK;
3803 }
3804
3805 /********************************************************************
3806  ********************************************************************/
3807
3808 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3809                                           const char *printername)
3810 {
3811         if (dm == NULL) {
3812                 return;
3813         }
3814
3815         dm->devicename = talloc_strndup(dm, printername,
3816                                         MIN(strlen(printername), 31));
3817 }
3818
3819 /********************************************************************
3820  * construct_printer_info_0
3821  * fill a printer_info_0 struct
3822  ********************************************************************/
3823
3824 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3825                                       const struct auth_session_info *session_info,
3826                                       struct messaging_context *msg_ctx,
3827                                       struct spoolss_PrinterInfo2 *info2,
3828                                       const char *servername,
3829                                       struct spoolss_PrinterInfo0 *r,
3830                                       int snum)
3831 {
3832         int count;
3833         struct printer_session_counter *session_counter;
3834         struct timeval setuptime;
3835         print_status_struct status;
3836         WERROR result;
3837
3838         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3839         if (!W_ERROR_IS_OK(result)) {
3840                 return result;
3841         }
3842
3843         if (servername) {
3844                 r->servername = talloc_strdup(mem_ctx, servername);
3845                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3846         } else {
3847                 r->servername = NULL;
3848         }
3849
3850         count = print_queue_length(msg_ctx, snum, &status);
3851
3852         /* check if we already have a counter for this printer */
3853         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3854                 if (session_counter->snum == snum)
3855                         break;
3856         }
3857
3858         /* it's the first time, add it to the list */
3859         if (session_counter == NULL) {
3860                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3861                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3862                 session_counter->snum           = snum;
3863                 session_counter->counter        = 0;
3864                 DLIST_ADD(counter_list, session_counter);
3865         }
3866
3867         /* increment it */
3868         session_counter->counter++;
3869
3870         r->cjobs                        = count;
3871         r->total_jobs                   = 0;
3872         r->total_bytes                  = 0;
3873
3874         get_startup_time(&setuptime);
3875         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3876
3877         /* JFM:
3878          * the global_counter should be stored in a TDB as it's common to all the clients
3879          * and should be zeroed on samba startup
3880          */
3881         r->global_counter               = session_counter->counter;
3882         r->total_pages                  = 0;
3883         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3884         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3885         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3886         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3887         r->spooling                     = 0;
3888         r->max_spooling                 = 0;
3889         r->session_counter              = session_counter->counter;
3890         r->num_error_out_of_paper       = 0x0;
3891         r->num_error_not_ready          = 0x0;          /* number of print failure */
3892         r->job_error                    = 0x0;
3893         r->number_of_processors         = 0x1;
3894         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3895         r->high_part_total_bytes        = 0x0;
3896
3897         /* ChangeID in milliseconds*/
3898         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3899                                     info2->sharename, &r->change_id);
3900
3901         r->last_error                   = WERR_OK;
3902         r->status                       = nt_printq_status(status.status);
3903         r->enumerate_network_printers   = 0x0;
3904         r->c_setprinter                 = 0x0;
3905         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3906         r->processor_level              = 0x6;          /* 6  ???*/
3907         r->ref_ic                       = 0;
3908         r->reserved2                    = 0;
3909         r->reserved3                    = 0;
3910
3911         return WERR_OK;
3912 }
3913
3914
3915 /********************************************************************
3916  * construct_printer_info1
3917  * fill a spoolss_PrinterInfo1 struct
3918 ********************************************************************/
3919
3920 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3921                                       const struct spoolss_PrinterInfo2 *info2,
3922                                       uint32_t flags,
3923                                       const char *servername,
3924                                       struct spoolss_PrinterInfo1 *r,
3925                                       int snum)
3926 {
3927         WERROR result;
3928
3929         r->flags                = flags;
3930
3931         if (info2->comment == NULL || info2->comment[0] == '\0') {
3932                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3933         } else {
3934                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3935         }
3936         W_ERROR_HAVE_NO_MEMORY(r->comment);
3937
3938         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3939         if (!W_ERROR_IS_OK(result)) {
3940                 return result;
3941         }
3942
3943         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3944                                                   r->name,
3945                                                   info2->drivername,
3946                                                   r->comment);
3947         W_ERROR_HAVE_NO_MEMORY(r->description);
3948
3949         return WERR_OK;
3950 }
3951
3952 /********************************************************************
3953  * construct_printer_info2
3954  * fill a spoolss_PrinterInfo2 struct
3955 ********************************************************************/
3956
3957 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3958                                       struct messaging_context *msg_ctx,
3959                                       const struct spoolss_PrinterInfo2 *info2,
3960                                       const char *servername,
3961                                       struct spoolss_PrinterInfo2 *r,
3962                                       int snum)
3963 {
3964         int count;
3965         print_status_struct status;
3966         WERROR result;
3967
3968         count = print_queue_length(msg_ctx, snum, &status);
3969
3970         if (servername) {
3971                 r->servername           = talloc_strdup(mem_ctx, servername);
3972                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3973         } else {
3974                 r->servername           = NULL;
3975         }
3976
3977         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3978         if (!W_ERROR_IS_OK(result)) {
3979                 return result;
3980         }
3981
3982         r->sharename            = talloc_strdup(mem_ctx, lp_servicename(snum));
3983         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3984         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3985         W_ERROR_HAVE_NO_MEMORY(r->portname);
3986         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3987         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3988
3989         if (info2->comment[0] == '\0') {
3990                 r->comment      = talloc_strdup(mem_ctx, lp_comment(snum));
3991         } else {
3992                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
3993         }
3994         W_ERROR_HAVE_NO_MEMORY(r->comment);
3995
3996         r->location     = talloc_strdup(mem_ctx, info2->location);
3997         if (info2->location[0] == '\0') {
3998                 const char *loc = NULL;
3999                 NTSTATUS nt_status;
4000
4001                 nt_status = printer_list_get_printer(mem_ctx,
4002                                                      info2->sharename,
4003                                                      NULL,
4004                                                      &loc,
4005                                                      NULL);
4006                 if (NT_STATUS_IS_OK(nt_status)) {
4007                         if (loc != NULL) {
4008                                 r->location = talloc_strdup(mem_ctx, loc);
4009                         }
4010                 }
4011         }
4012         W_ERROR_HAVE_NO_MEMORY(r->location);
4013
4014         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4015         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4016         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4017         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4018         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4019         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4020         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4021         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4022
4023         r->attributes           = info2->attributes;
4024
4025         r->priority             = info2->priority;
4026         r->defaultpriority      = info2->defaultpriority;
4027         r->starttime            = info2->starttime;
4028         r->untiltime            = info2->untiltime;
4029         r->status               = nt_printq_status(status.status);
4030         r->cjobs                = count;
4031         r->averageppm           = info2->averageppm;
4032
4033         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4034         if (!r->devmode) {
4035                 DEBUG(8,("Returning NULL Devicemode!\n"));
4036         }
4037
4038         compose_devicemode_devicename(r->devmode, r->printername);
4039
4040         r->secdesc = NULL;
4041
4042         if (info2->secdesc != NULL) {
4043                 /* don't use talloc_steal() here unless you do a deep steal of all
4044                    the SEC_DESC members */
4045
4046                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4047         }
4048
4049         return WERR_OK;
4050 }
4051
4052 /********************************************************************
4053  * construct_printer_info3
4054  * fill a spoolss_PrinterInfo3 struct
4055  ********************************************************************/
4056
4057 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4058                                       const struct spoolss_PrinterInfo2 *info2,
4059                                       const char *servername,
4060                                       struct spoolss_PrinterInfo3 *r,
4061                                       int snum)
4062 {
4063         /* These are the components of the SD we are returning. */
4064
4065         if (info2->secdesc != NULL) {
4066                 /* don't use talloc_steal() here unless you do a deep steal of all
4067                    the SEC_DESC members */
4068
4069                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4070                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4071         }
4072
4073         return WERR_OK;
4074 }
4075
4076 /********************************************************************
4077  * construct_printer_info4
4078  * fill a spoolss_PrinterInfo4 struct
4079  ********************************************************************/
4080
4081 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4082                                       const struct spoolss_PrinterInfo2 *info2,
4083                                       const char *servername,
4084                                       struct spoolss_PrinterInfo4 *r,
4085                                       int snum)
4086 {
4087         WERROR result;
4088
4089         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4090         if (!W_ERROR_IS_OK(result)) {
4091                 return result;
4092         }
4093
4094         if (servername) {
4095                 r->servername   = talloc_strdup(mem_ctx, servername);
4096                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4097         } else {
4098                 r->servername = NULL;
4099         }
4100
4101         r->attributes   = info2->attributes;
4102
4103         return WERR_OK;
4104 }
4105
4106 /********************************************************************
4107  * construct_printer_info5
4108  * fill a spoolss_PrinterInfo5 struct
4109  ********************************************************************/
4110
4111 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4112                                       const struct spoolss_PrinterInfo2 *info2,
4113                                       const char *servername,
4114                                       struct spoolss_PrinterInfo5 *r,
4115                                       int snum)
4116 {
4117         WERROR result;
4118
4119         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4120         if (!W_ERROR_IS_OK(result)) {
4121                 return result;
4122         }
4123
4124         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4125         W_ERROR_HAVE_NO_MEMORY(r->portname);
4126
4127         r->attributes   = info2->attributes;
4128
4129         /* these two are not used by NT+ according to MSDN */
4130         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4131         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4132
4133         return WERR_OK;
4134 }
4135
4136 /********************************************************************
4137  * construct_printer_info_6
4138  * fill a spoolss_PrinterInfo6 struct
4139  ********************************************************************/
4140
4141 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4142                                       struct messaging_context *msg_ctx,
4143                                       const struct spoolss_PrinterInfo2 *info2,
4144                                       const char *servername,
4145                                       struct spoolss_PrinterInfo6 *r,
4146                                       int snum)
4147 {
4148         print_status_struct status;
4149
4150         print_queue_length(msg_ctx, snum, &status);
4151
4152         r->status = nt_printq_status(status.status);
4153
4154         return WERR_OK;
4155 }
4156
4157 /********************************************************************
4158  * construct_printer_info7
4159  * fill a spoolss_PrinterInfo7 struct
4160  ********************************************************************/
4161
4162 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4163                                       struct messaging_context *msg_ctx,
4164                                       const char *servername,
4165                                       struct spoolss_PrinterInfo7 *r,
4166                                       int snum)
4167 {
4168         const struct auth_session_info *session_info = get_session_info_system();
4169         struct GUID guid;
4170
4171         if (is_printer_published(mem_ctx, session_info, msg_ctx,
4172                                  servername,
4173                                  lp_servicename(snum), &guid, NULL)) {
4174                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4175                 r->action = DSPRINT_PUBLISH;
4176         } else {
4177                 r->guid = talloc_strdup(mem_ctx, "");
4178                 r->action = DSPRINT_UNPUBLISH;
4179         }
4180         W_ERROR_HAVE_NO_MEMORY(r->guid);
4181
4182         return WERR_OK;
4183 }
4184
4185 /********************************************************************
4186  * construct_printer_info8
4187  * fill a spoolss_PrinterInfo8 struct
4188  ********************************************************************/
4189
4190 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4191                                       const struct spoolss_PrinterInfo2 *info2,
4192                                       const char *servername,
4193                                       struct spoolss_DeviceModeInfo *r,
4194                                       int snum)
4195 {
4196         WERROR result;
4197         const char *printername;
4198
4199         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4200         if (!W_ERROR_IS_OK(result)) {
4201                 return result;
4202         }
4203
4204         copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4205         if (!r->devmode) {
4206                 DEBUG(8,("Returning NULL Devicemode!\n"));
4207         }
4208
4209         compose_devicemode_devicename(r->devmode, printername);
4210
4211         return WERR_OK;
4212 }
4213
4214
4215 /********************************************************************
4216 ********************************************************************/
4217
4218 static bool snum_is_shared_printer(int snum)
4219 {
4220         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4221 }
4222
4223 /********************************************************************
4224  Spoolss_enumprinters.
4225 ********************************************************************/
4226
4227 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4228                                            const struct auth_session_info *session_info,
4229                                            struct messaging_context *msg_ctx,
4230                                            const char *servername,
4231                                            uint32_t level,
4232                                            uint32_t flags,
4233                                            union spoolss_PrinterInfo **info_p,
4234                                            uint32_t *count_p)
4235 {
4236         int snum;
4237         int n_services = lp_numservices();
4238         union spoolss_PrinterInfo *info = NULL;
4239         uint32_t count = 0;
4240         WERROR result = WERR_OK;
4241         struct dcerpc_binding_handle *b = NULL;
4242         TALLOC_CTX *tmp_ctx = NULL;
4243
4244         tmp_ctx = talloc_new(mem_ctx);
4245         if (!tmp_ctx) {
4246                 return WERR_NOMEM;
4247         }
4248
4249         *count_p = 0;
4250         *info_p = NULL;
4251
4252         for (snum = 0; snum < n_services; snum++) {
4253
4254                 const char *printer;
4255                 struct spoolss_PrinterInfo2 *info2;
4256
4257                 if (!snum_is_shared_printer(snum)) {
4258                         continue;
4259                 }
4260
4261                 printer = lp_const_servicename(snum);
4262
4263                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4264                         printer, snum));
4265
4266                 if (b == NULL) {
4267                         result = winreg_printer_binding_handle(tmp_ctx,
4268                                                                session_info,
4269                                                                msg_ctx,
4270                                                                &b);
4271                         if (!W_ERROR_IS_OK(result)) {
4272                                 goto out;
4273                         }
4274                 }
4275
4276                 result = winreg_create_printer(tmp_ctx, b,
4277                                                printer);
4278                 if (!W_ERROR_IS_OK(result)) {
4279                         goto out;
4280                 }
4281
4282                 info = talloc_realloc(tmp_ctx, info,
4283                                             union spoolss_PrinterInfo,
4284                                             count + 1);
4285                 if (!info) {
4286                         result = WERR_NOMEM;
4287                         goto out;
4288                 }
4289
4290                 result = winreg_get_printer(tmp_ctx, b,
4291                                             printer, &info2);
4292                 if (!W_ERROR_IS_OK(result)) {
4293                         goto out;
4294                 }
4295
4296                 switch (level) {
4297                 case 0:
4298                         result = construct_printer_info0(info, session_info,
4299                                                          msg_ctx, info2,
4300                                                          servername,
4301                                                          &info[count].info0, snum);
4302                         break;
4303                 case 1:
4304                         result = construct_printer_info1(info, info2, flags,
4305                                                          servername,
4306                                                          &info[count].info1, snum);
4307                         break;
4308                 case 2:
4309                         result = construct_printer_info2(info, msg_ctx, info2,
4310                                                          servername,
4311                                                          &info[count].info2, snum);
4312                         break;
4313                 case 4:
4314                         result = construct_printer_info4(info, info2,
4315                                                          servername,
4316                                                          &info[count].info4, snum);
4317                         break;
4318                 case 5:
4319                         result = construct_printer_info5(info, info2,
4320                                                          servername,
4321                                                          &info[count].info5, snum);
4322                         break;
4323
4324                 default:
4325                         result = WERR_UNKNOWN_LEVEL;
4326                         goto out;
4327                 }
4328
4329                 if (!W_ERROR_IS_OK(result)) {
4330                         goto out;
4331                 }
4332
4333                 count++;
4334         }
4335
4336 out:
4337         if (W_ERROR_IS_OK(result)) {
4338                 *info_p = talloc_move(mem_ctx, &info);
4339                 *count_p = count;
4340         }
4341
4342         talloc_free(tmp_ctx);
4343
4344         return result;
4345 }
4346
4347 /********************************************************************
4348  * handle enumeration of printers at level 0
4349  ********************************************************************/
4350
4351 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4352                                   const struct auth_session_info *session_info,
4353                                   struct messaging_context *msg_ctx,
4354                                   uint32_t flags,
4355                                   const char *servername,
4356                                   union spoolss_PrinterInfo **info,
4357                                   uint32_t *count)
4358 {
4359         DEBUG(4,("enum_all_printers_info_0\n"));
4360
4361         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4362                                             servername, 0, flags, info, count);
4363 }
4364
4365
4366 /********************************************************************
4367 ********************************************************************/
4368
4369 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4370                                        const struct auth_session_info *session_info,
4371                                        struct messaging_context *msg_ctx,
4372                                        const char *servername,
4373                                        uint32_t flags,
4374                                        union spoolss_PrinterInfo **info,
4375                                        uint32_t *count)
4376 {
4377         DEBUG(4,("enum_all_printers_info_1\n"));
4378
4379         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4380                                             servername, 1, flags, info, count);
4381 }
4382
4383 /********************************************************************
4384  enum_all_printers_info_1_local.
4385 *********************************************************************/
4386
4387 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4388                                              const struct auth_session_info *session_info,
4389                                              struct messaging_context *msg_ctx,
4390                                              const char *servername,
4391                                              union spoolss_PrinterInfo **info,
4392                                              uint32_t *count)
4393 {
4394         DEBUG(4,("enum_all_printers_info_1_local\n"));
4395
4396         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4397                                         servername, PRINTER_ENUM_ICON8, info, count);
4398 }
4399
4400 /********************************************************************
4401  enum_all_printers_info_1_name.
4402 *********************************************************************/
4403
4404 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4405                                             const struct auth_session_info *session_info,
4406                                             struct messaging_context *msg_ctx,
4407                                             const char *servername,
4408                                             union spoolss_PrinterInfo **info,
4409                                             uint32_t *count)
4410 {
4411         const char *s = servername;
4412
4413         DEBUG(4,("enum_all_printers_info_1_name\n"));
4414
4415         if ((servername[0] == '\\') && (servername[1] == '\\')) {
4416                 s = servername + 2;
4417         }
4418
4419         if (!is_myname_or_ipaddr(s)) {
4420                 return WERR_INVALID_NAME;
4421         }
4422
4423         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4424                                         servername, PRINTER_ENUM_ICON8, info, count);
4425 }
4426
4427 /********************************************************************
4428  enum_all_printers_info_1_network.
4429 *********************************************************************/
4430
4431 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4432                                                const struct auth_session_info *session_info,
4433                                                struct messaging_context *msg_ctx,
4434                                                const char *servername,
4435                                                union spoolss_PrinterInfo **info,
4436                                                uint32_t *count)
4437 {
4438         const char *s = servername;
4439
4440         DEBUG(4,("enum_all_printers_info_1_network\n"));
4441
4442         /* If we respond to a enum_printers level 1 on our name with flags
4443            set to PRINTER_ENUM_REMOTE with a list of printers then these
4444            printers incorrectly appear in the APW browse list.
4445            Specifically the printers for the server appear at the workgroup
4446            level where all the other servers in the domain are
4447            listed. Windows responds to this call with a
4448            WERR_CAN_NOT_COMPLETE so we should do the same. */
4449
4450         if (servername[0] == '\\' && servername[1] == '\\') {
4451                  s = servername + 2;
4452         }
4453
4454         if (is_myname_or_ipaddr(s)) {
4455                  return WERR_CAN_NOT_COMPLETE;
4456         }
4457
4458         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4459                                         servername, PRINTER_ENUM_NAME, info, count);
4460 }
4461
4462 /********************************************************************
4463  * api_spoolss_enumprinters
4464  *
4465  * called from api_spoolss_enumprinters (see this to understand)
4466  ********************************************************************/
4467
4468 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4469                                        const struct auth_session_info *session_info,
4470                                        struct messaging_context *msg_ctx,
4471                                        const char *servername,
4472                                        union spoolss_PrinterInfo **info,
4473                                        uint32_t *count)
4474 {
4475         DEBUG(4,("enum_all_printers_info_2\n"));
4476
4477         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4478                                             servername, 2, 0, info, count);
4479 }
4480
4481 /********************************************************************
4482  * handle enumeration of printers at level 1
4483  ********************************************************************/
4484
4485 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4486                                   const struct auth_session_info *session_info,
4487                                   struct messaging_context *msg_ctx,
4488                                   uint32_t flags,
4489                                   const char *servername,
4490                                   union spoolss_PrinterInfo **info,
4491                                   uint32_t *count)
4492 {
4493         /* Not all the flags are equals */
4494
4495         if (flags & PRINTER_ENUM_LOCAL) {
4496                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4497                                                       msg_ctx, servername, info, count);
4498         }
4499
4500         if (flags & PRINTER_ENUM_NAME) {
4501                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4502                                                      msg_ctx, servername, info,
4503                                                      count);
4504         }
4505
4506         if (flags & PRINTER_ENUM_NETWORK) {
4507                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4508                                                         msg_ctx, servername, info,
4509                                                         count);
4510         }
4511
4512         return WERR_OK; /* NT4sp5 does that */
4513 }
4514
4515 /********************************************************************
4516  * handle enumeration of printers at level 2
4517  ********************************************************************/
4518
4519 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4520                                   const struct auth_session_info *session_info,
4521                                   struct messaging_context *msg_ctx,
4522                                   uint32_t flags,
4523                                   const char *servername,
4524                                   union spoolss_PrinterInfo **info,
4525                                   uint32_t *count)
4526 {
4527         if (flags & PRINTER_ENUM_LOCAL) {
4528
4529                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4530                                                 servername,
4531                                                 info, count);
4532         }
4533
4534         if (flags & PRINTER_ENUM_NAME) {
4535                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4536                         return WERR_INVALID_NAME;
4537                 }
4538
4539                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4540                                                 servername,
4541                                                 info, count);
4542         }
4543
4544         if (flags & PRINTER_ENUM_REMOTE) {
4545                 return WERR_UNKNOWN_LEVEL;
4546         }
4547
4548         return WERR_OK;
4549 }
4550
4551 /********************************************************************
4552  * handle enumeration of printers at level 4
4553  ********************************************************************/
4554
4555 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4556                                   const struct auth_session_info *session_info,
4557                                   struct messaging_context *msg_ctx,
4558                                   uint32_t flags,
4559                                   const char *servername,
4560                                   union spoolss_PrinterInfo **info,
4561                                   uint32_t *count)
4562 {
4563         DEBUG(4,("enum_all_printers_info_4\n"));
4564
4565         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4566                                             servername, 4, flags, info, count);
4567 }
4568
4569
4570 /********************************************************************
4571  * handle enumeration of printers at level 5
4572  ********************************************************************/
4573
4574 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4575                                   const struct auth_session_info *session_info,
4576                                   struct messaging_context *msg_ctx,
4577                                   uint32_t flags,
4578                                   const char *servername,
4579                                   union spoolss_PrinterInfo **info,
4580                                   uint32_t *count)
4581 {
4582         DEBUG(4,("enum_all_printers_info_5\n"));
4583
4584         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4585                                             servername, 5, flags, info, count);
4586 }
4587
4588 /****************************************************************
4589  _spoolss_EnumPrinters
4590 ****************************************************************/
4591
4592 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4593                              struct spoolss_EnumPrinters *r)
4594 {
4595         const struct auth_session_info *session_info = get_session_info_system();
4596         WERROR result;
4597
4598         /* that's an [in out] buffer */
4599
4600         if (!r->in.buffer && (r->in.offered != 0)) {
4601                 return WERR_INVALID_PARAM;
4602         }
4603
4604         DEBUG(4,("_spoolss_EnumPrinters\n"));
4605
4606         *r->out.needed = 0;
4607         *r->out.count = 0;
4608         *r->out.info = NULL;
4609
4610         /*
4611          * Level 1:
4612          *          flags==PRINTER_ENUM_NAME
4613          *           if name=="" then enumerates all printers
4614          *           if name!="" then enumerate the printer
4615          *          flags==PRINTER_ENUM_REMOTE
4616          *          name is NULL, enumerate printers
4617          * Level 2: name!="" enumerates printers, name can't be NULL
4618          * Level 3: doesn't exist
4619          * Level 4: does a local registry lookup
4620          * Level 5: same as Level 2
4621          */
4622
4623         if (r->in.server && r->in.server[0] == '\0') {
4624                 r->in.server = NULL;
4625         }
4626
4627         switch (r->in.level) {
4628         case 0:
4629                 result = enumprinters_level0(p->mem_ctx, session_info,
4630                                              p->msg_ctx, r->in.flags,
4631                                              r->in.server,
4632                                              r->out.info, r->out.count);
4633                 break;
4634         case 1:
4635                 result = enumprinters_level1(p->mem_ctx, session_info,
4636                                              p->msg_ctx, r->in.flags,
4637                                              r->in.server,
4638                                              r->out.info, r->out.count);
4639                 break;
4640         case 2:
4641                 result = enumprinters_level2(p->mem_ctx, session_info,
4642                                              p->msg_ctx, r->in.flags,
4643                                              r->in.server,
4644                                              r->out.info, r->out.count);
4645                 break;
4646         case 4:
4647                 result = enumprinters_level4(p->mem_ctx, session_info,
4648                                              p->msg_ctx, r->in.flags,
4649                                              r->in.server,
4650                                              r->out.info, r->out.count);
4651                 break;
4652         case 5:
4653                 result = enumprinters_level5(p->mem_ctx, session_info,
4654                                              p->msg_ctx, r->in.flags,
4655                                              r->in.server,
4656                                              r->out.info, r->out.count);
4657                 break;
4658         default:
4659                 return WERR_UNKNOWN_LEVEL;
4660         }
4661
4662         if (!W_ERROR_IS_OK(result)) {
4663                 return result;
4664         }
4665
4666         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4667                                                      spoolss_EnumPrinters,
4668                                                      *r->out.info, r->in.level,
4669                                                      *r->out.count);
4670         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4671         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4672
4673         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4674 }
4675
4676 /****************************************************************
4677  _spoolss_GetPrinter
4678 ****************************************************************/
4679
4680 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4681                            struct spoolss_GetPrinter *r)
4682 {
4683         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4684         struct spoolss_PrinterInfo2 *info2 = NULL;
4685         WERROR result = WERR_OK;
4686         int snum;
4687
4688         /* that's an [in out] buffer */
4689
4690         if (!r->in.buffer && (r->in.offered != 0)) {
4691                 return WERR_INVALID_PARAM;
4692         }
4693
4694         *r->out.needed = 0;
4695
4696         if (Printer == NULL) {
4697                 return WERR_BADFID;
4698         }
4699
4700         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4701                 return WERR_BADFID;
4702         }
4703
4704         result = winreg_get_printer_internal(p->mem_ctx,
4705                                     get_session_info_system(),
4706                                     p->msg_ctx,
4707                                     lp_const_servicename(snum),
4708                                     &info2);
4709         if (!W_ERROR_IS_OK(result)) {
4710                 goto out;
4711         }
4712
4713         switch (r->in.level) {
4714         case 0:
4715                 result = construct_printer_info0(p->mem_ctx,
4716                                                  get_session_info_system(),
4717                                                  p->msg_ctx,
4718                                                  info2,
4719                                                  Printer->servername,
4720                                                  &r->out.info->info0,
4721                                                  snum);
4722                 break;
4723         case 1:
4724                 result = construct_printer_info1(p->mem_ctx, info2,
4725                                                  PRINTER_ENUM_ICON8,
4726                                                  Printer->servername,
4727                                                  &r->out.info->info1, snum);
4728                 break;
4729         case 2:
4730                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4731                                                  Printer->servername,
4732                                                  &r->out.info->info2, snum);
4733                 break;
4734         case 3:
4735                 result = construct_printer_info3(p->mem_ctx, info2,
4736                                                  Printer->servername,
4737                                                  &r->out.info->info3, snum);
4738                 break;
4739         case 4:
4740                 result = construct_printer_info4(p->mem_ctx, info2,
4741                                                  Printer->servername,
4742                                                  &r->out.info->info4, snum);
4743                 break;
4744         case 5:
4745                 result = construct_printer_info5(p->mem_ctx, info2,
4746                                                  Printer->servername,
4747                                                  &r->out.info->info5, snum);
4748                 break;
4749         case 6:
4750                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4751                                                  Printer->servername,
4752                                                  &r->out.info->info6, snum);
4753                 break;
4754         case 7:
4755                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4756                                                  Printer->servername,
4757                                                  &r->out.info->info7, snum);
4758                 break;
4759         case 8:
4760                 result = construct_printer_info8(p->mem_ctx, info2,
4761                                                  Printer->servername,
4762                                                  &r->out.info->info8, snum);
4763                 break;
4764         default:
4765                 result = WERR_UNKNOWN_LEVEL;
4766                 break;
4767         }
4768         TALLOC_FREE(info2);
4769
4770  out:
4771         if (!W_ERROR_IS_OK(result)) {
4772                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4773                           r->in.level, win_errstr(result)));
4774                 TALLOC_FREE(r->out.info);
4775                 return result;
4776         }
4777
4778         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4779                                                r->out.info, r->in.level);
4780         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4781
4782         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4783 }
4784
4785 /********************************************************************
4786  ********************************************************************/
4787
4788 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4789         do { \
4790                 if (in && strlen(in)) { \
4791                         out = talloc_strdup(mem_ctx, in); \
4792                 } else { \
4793                         out = talloc_strdup(mem_ctx, ""); \
4794                 } \
4795                 W_ERROR_HAVE_NO_MEMORY(out); \
4796         } while (0);
4797
4798 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4799         do { \
4800                 if (in && strlen(in)) { \
4801                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4802                 } else { \
4803                         out = talloc_strdup(mem_ctx, ""); \
4804                 } \
4805                 W_ERROR_HAVE_NO_MEMORY(out); \
4806         } while (0);
4807
4808 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4809                                                   const char **string_array,
4810                                                   const char ***presult,
4811                                                   const char *cservername,
4812                                                   const char *arch,
4813                                                   int version)
4814 {
4815         int i, num_strings = 0;
4816         const char **array = NULL;
4817
4818         if (string_array == NULL) {
4819                 return WERR_INVALID_PARAMETER;
4820         }
4821
4822         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4823                 const char *str = NULL;
4824
4825                 if (cservername == NULL || arch == NULL) {
4826                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4827                 } else {
4828                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4829                 }
4830
4831                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4832                         TALLOC_FREE(array);
4833                         return WERR_NOMEM;
4834                 }
4835         }
4836
4837         if (i > 0) {
4838                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4839                              &array, &num_strings);
4840         }
4841
4842         if (presult) {
4843                 *presult = array;
4844         }
4845
4846         return WERR_OK;
4847 }
4848
4849 /********************************************************************
4850  * fill a spoolss_DriverInfo1 struct
4851  ********************************************************************/
4852
4853 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4854                                         struct spoolss_DriverInfo1 *r,
4855                                         const struct spoolss_DriverInfo8 *driver,
4856                                         const char *servername)
4857 {
4858         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4859         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4860
4861         return WERR_OK;
4862 }
4863
4864 /********************************************************************
4865  * fill a spoolss_DriverInfo2 struct
4866  ********************************************************************/
4867
4868 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4869                                         struct spoolss_DriverInfo2 *r,
4870                                         const struct spoolss_DriverInfo8 *driver,
4871                                         const char *servername)
4872
4873 {
4874         const char *cservername = canon_servername(servername);
4875
4876         r->version              = driver->version;
4877
4878         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4879         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4880         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4881         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4882
4883         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4884                                driver->architecture,
4885                                driver->version,
4886                                driver->driver_path,
4887                                r->driver_path);
4888
4889         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4890                                driver->architecture,
4891                                driver->version,
4892                                driver->data_file,
4893                                r->data_file);
4894
4895         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4896                                driver->architecture,
4897                                driver->version,
4898                                driver->config_file,
4899                                r->config_file);
4900
4901         return WERR_OK;
4902 }
4903
4904 /********************************************************************
4905  * fill a spoolss_DriverInfo3 struct
4906  ********************************************************************/
4907
4908 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4909                                         struct spoolss_DriverInfo3 *r,
4910                                         const struct spoolss_DriverInfo8 *driver,
4911                                         const char *servername)
4912 {
4913         const char *cservername = canon_servername(servername);
4914
4915         r->version              = driver->version;
4916
4917         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4918         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4919         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4920         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4921
4922         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4923                                driver->architecture,
4924                                driver->version,
4925                                driver->driver_path,
4926                                r->driver_path);
4927
4928         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4929                                driver->architecture,
4930                                driver->version,
4931                                driver->data_file,
4932                                r->data_file);
4933
4934         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4935                                driver->architecture,
4936                                driver->version,
4937                                driver->config_file,
4938                                r->config_file);
4939
4940         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4941                                driver->architecture,
4942                                driver->version,
4943                                driver->help_file,
4944                                r->help_file);
4945
4946         FILL_DRIVER_STRING(mem_ctx,
4947                            driver->monitor_name,
4948                            r->monitor_name);
4949
4950         FILL_DRIVER_STRING(mem_ctx,
4951                            driver->default_datatype,
4952                            r->default_datatype);
4953
4954         return string_array_from_driver_info(mem_ctx,
4955                                              driver->dependent_files,
4956                                              &r->dependent_files,
4957                                              cservername,
4958                                              driver->architecture,
4959                                              driver->version);
4960 }
4961
4962 /********************************************************************
4963  * fill a spoolss_DriverInfo4 struct
4964  ********************************************************************/
4965
4966 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4967                                         struct spoolss_DriverInfo4 *r,
4968                                         const struct spoolss_DriverInfo8 *driver,
4969                                         const char *servername)
4970 {
4971         const char *cservername = canon_servername(servername);
4972         WERROR result;
4973
4974         r->version              = driver->version;
4975
4976         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4977         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4978         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4979         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4980
4981         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4982                                driver->architecture,
4983                                driver->version,
4984                                driver->driver_path,
4985                                r->driver_path);
4986
4987         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4988                                driver->architecture,
4989                                driver->version,
4990                                driver->data_file,
4991                                r->data_file);
4992
4993         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4994                                driver->architecture,
4995                                driver->version,
4996                                driver->config_file,
4997                                r->config_file);
4998
4999         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5000                                driver->architecture,
5001                                driver->version,
5002                                driver->help_file,
5003                                r->help_file);
5004
5005         result = string_array_from_driver_info(mem_ctx,
5006                                                driver->dependent_files,
5007                                                &r->dependent_files,
5008                                                cservername,
5009                                                driver->architecture,
5010                                                driver->version);
5011         if (!W_ERROR_IS_OK(result)) {
5012                 return result;
5013         }
5014
5015         FILL_DRIVER_STRING(mem_ctx,
5016                            driver->monitor_name,
5017                            r->monitor_name);
5018
5019         FILL_DRIVER_STRING(mem_ctx,
5020                            driver->default_datatype,
5021                            r->default_datatype);
5022
5023
5024         result = string_array_from_driver_info(mem_ctx,
5025                                                driver->previous_names,
5026                                                &r->previous_names,
5027                                                NULL, NULL, 0);
5028
5029         return result;
5030 }
5031
5032 /********************************************************************
5033  * fill a spoolss_DriverInfo5 struct
5034  ********************************************************************/
5035
5036 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5037                                         struct spoolss_DriverInfo5 *r,
5038                                         const struct spoolss_DriverInfo8 *driver,
5039                                         const char *servername)
5040 {
5041         const char *cservername = canon_servername(servername);
5042
5043         r->version              = driver->version;
5044
5045         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5046         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5047         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5048         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5049
5050         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5051                                driver->architecture,
5052                                driver->version,
5053                                driver->driver_path,
5054                                r->driver_path);
5055
5056         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5057                                driver->architecture,
5058                                driver->version,
5059                                driver->data_file,
5060                                r->data_file);
5061
5062         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5063                                driver->architecture,
5064                                driver->version,
5065                                driver->config_file,
5066                                r->config_file);
5067
5068         r->driver_attributes    = 0;
5069         r->config_version       = 0;
5070         r->driver_version       = 0;
5071
5072         return WERR_OK;
5073 }
5074 /********************************************************************
5075  * fill a spoolss_DriverInfo6 struct
5076  ********************************************************************/
5077
5078 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5079                                         struct spoolss_DriverInfo6 *r,
5080                                         const struct spoolss_DriverInfo8 *driver,
5081                                         const char *servername)
5082 {
5083         const char *cservername = canon_servername(servername);
5084         WERROR result;
5085
5086         r->version              = driver->version;
5087
5088         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5089         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5090         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5091         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5092
5093         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5094                                driver->architecture,
5095                                driver->version,
5096                                driver->driver_path,
5097                                r->driver_path);
5098
5099         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5100                                driver->architecture,
5101                                driver->version,
5102                                driver->data_file,
5103                                r->data_file);
5104
5105         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5106                                driver->architecture,
5107                                driver->version,
5108                                driver->config_file,
5109                                r->config_file);
5110
5111         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5112                                driver->architecture,
5113                                driver->version,
5114                                driver->help_file,
5115                                r->help_file);
5116
5117         FILL_DRIVER_STRING(mem_ctx,
5118                            driver->monitor_name,
5119                            r->monitor_name);
5120
5121         FILL_DRIVER_STRING(mem_ctx,
5122                            driver->default_datatype,
5123                            r->default_datatype);
5124
5125         result = string_array_from_driver_info(mem_ctx,
5126                                                driver->dependent_files,
5127                                                &r->dependent_files,
5128                                                cservername,
5129                                                driver->architecture,
5130                                                driver->version);
5131         if (!W_ERROR_IS_OK(result)) {
5132                 return result;
5133         }
5134
5135         result = string_array_from_driver_info(mem_ctx,
5136                                                driver->previous_names,
5137                                                &r->previous_names,
5138                                                NULL, NULL, 0);
5139         if (!W_ERROR_IS_OK(result)) {
5140                 return result;
5141         }
5142
5143         r->driver_date          = driver->driver_date;
5144         r->driver_version       = driver->driver_version;
5145
5146         FILL_DRIVER_STRING(mem_ctx,
5147                            driver->manufacturer_name,
5148                            r->manufacturer_name);
5149         FILL_DRIVER_STRING(mem_ctx,
5150                            driver->manufacturer_url,
5151                            r->manufacturer_url);
5152         FILL_DRIVER_STRING(mem_ctx,
5153                            driver->hardware_id,
5154                            r->hardware_id);
5155         FILL_DRIVER_STRING(mem_ctx,
5156                            driver->provider,
5157                            r->provider);
5158
5159         return WERR_OK;
5160 }
5161
5162 /********************************************************************
5163  * fill a spoolss_DriverInfo8 struct
5164  ********************************************************************/
5165
5166 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5167                                         struct spoolss_DriverInfo8 *r,
5168                                         const struct spoolss_DriverInfo8 *driver,
5169                                         const char *servername)
5170 {
5171         const char *cservername = canon_servername(servername);
5172         WERROR result;
5173
5174         r->version              = driver->version;
5175
5176         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5177         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5178         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5179         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5180
5181         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5182                                driver->architecture,
5183                                driver->version,
5184                                driver->driver_path,
5185                                r->driver_path);
5186
5187         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5188                                driver->architecture,
5189                                driver->version,
5190                                driver->data_file,
5191                                r->data_file);
5192
5193         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5194                                driver->architecture,
5195                                driver->version,
5196                                driver->config_file,
5197                                r->config_file);
5198
5199         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5200                                driver->architecture,
5201                                driver->version,
5202                                driver->help_file,
5203                                r->help_file);
5204
5205         FILL_DRIVER_STRING(mem_ctx,
5206                            driver->monitor_name,
5207                            r->monitor_name);
5208
5209         FILL_DRIVER_STRING(mem_ctx,
5210                            driver->default_datatype,
5211                            r->default_datatype);
5212
5213         result = string_array_from_driver_info(mem_ctx,
5214                                                driver->dependent_files,
5215                                                &r->dependent_files,
5216                                                cservername,
5217                                                driver->architecture,
5218                                                driver->version);
5219         if (!W_ERROR_IS_OK(result)) {
5220                 return result;
5221         }
5222
5223         result = string_array_from_driver_info(mem_ctx,
5224                                                driver->previous_names,
5225                                                &r->previous_names,
5226                                                NULL, NULL, 0);
5227         if (!W_ERROR_IS_OK(result)) {
5228                 return result;
5229         }
5230
5231         r->driver_date          = driver->driver_date;
5232         r->driver_version       = driver->driver_version;
5233
5234         FILL_DRIVER_STRING(mem_ctx,
5235                            driver->manufacturer_name,
5236                            r->manufacturer_name);
5237         FILL_DRIVER_STRING(mem_ctx,
5238                            driver->manufacturer_url,
5239                            r->manufacturer_url);
5240         FILL_DRIVER_STRING(mem_ctx,
5241                            driver->hardware_id,
5242                            r->hardware_id);
5243         FILL_DRIVER_STRING(mem_ctx,
5244                            driver->provider,
5245                            r->provider);
5246
5247         FILL_DRIVER_STRING(mem_ctx,
5248                            driver->print_processor,
5249                            r->print_processor);
5250         FILL_DRIVER_STRING(mem_ctx,
5251                            driver->vendor_setup,
5252                            r->vendor_setup);
5253
5254         result = string_array_from_driver_info(mem_ctx,
5255                                                driver->color_profiles,
5256                                                &r->color_profiles,
5257                                                NULL, NULL, 0);
5258         if (!W_ERROR_IS_OK(result)) {
5259                 return result;
5260         }
5261
5262         FILL_DRIVER_STRING(mem_ctx,
5263                            driver->inf_path,
5264                            r->inf_path);
5265
5266         r->printer_driver_attributes    = driver->printer_driver_attributes;
5267
5268         result = string_array_from_driver_info(mem_ctx,
5269                                                driver->core_driver_dependencies,
5270                                                &r->core_driver_dependencies,
5271                                                NULL, NULL, 0);
5272         if (!W_ERROR_IS_OK(result)) {
5273                 return result;
5274         }
5275
5276         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5277         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5278
5279         return WERR_OK;
5280 }
5281
5282 #if 0 /* disabled until marshalling issues are resolved - gd */
5283 /********************************************************************
5284  ********************************************************************/
5285
5286 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5287                                           struct spoolss_DriverFileInfo *r,
5288                                           const char *cservername,
5289                                           const char *file_name,
5290                                           enum spoolss_DriverFileType file_type,
5291                                           uint32_t file_version)
5292 {
5293         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5294                                           cservername, file_name);
5295         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5296         r->file_type    = file_type;
5297         r->file_version = file_version;
5298
5299         return WERR_OK;
5300 }
5301
5302 /********************************************************************
5303  ********************************************************************/
5304
5305 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5306                                                  const struct spoolss_DriverInfo8 *driver,
5307                                                  const char *cservername,
5308                                                  struct spoolss_DriverFileInfo **info_p,
5309                                                  uint32_t *count_p)
5310 {
5311         struct spoolss_DriverFileInfo *info = NULL;
5312         uint32_t count = 0;
5313         WERROR result;
5314         uint32_t i;
5315
5316         *info_p = NULL;
5317         *count_p = 0;
5318
5319         if (strlen(driver->driver_path)) {
5320                 info = talloc_realloc(mem_ctx, info,
5321                                             struct spoolss_DriverFileInfo,
5322                                             count + 1);
5323                 W_ERROR_HAVE_NO_MEMORY(info);
5324                 result = fill_spoolss_DriverFileInfo(info,
5325                                                      &info[count],
5326                                                      cservername,
5327                                                      driver->driver_path,
5328                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5329                                                      0);
5330                 W_ERROR_NOT_OK_RETURN(result);
5331                 count++;
5332         }
5333
5334         if (strlen(driver->config_file)) {
5335                 info = talloc_realloc(mem_ctx, info,
5336                                             struct spoolss_DriverFileInfo,
5337                                             count + 1);
5338                 W_ERROR_HAVE_NO_MEMORY(info);
5339                 result = fill_spoolss_DriverFileInfo(info,
5340                                                      &info[count],
5341                                                      cservername,
5342                                                      driver->config_file,
5343                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5344                                                      0);
5345                 W_ERROR_NOT_OK_RETURN(result);
5346                 count++;
5347         }
5348
5349         if (strlen(driver->data_file)) {
5350                 info = talloc_realloc(mem_ctx, info,
5351                                             struct spoolss_DriverFileInfo,
5352                                             count + 1);
5353                 W_ERROR_HAVE_NO_MEMORY(info);
5354                 result = fill_spoolss_DriverFileInfo(info,
5355                                                      &info[count],
5356                                                      cservername,
5357                                                      driver->data_file,
5358                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5359                                                      0);
5360                 W_ERROR_NOT_OK_RETURN(result);
5361                 count++;
5362         }
5363
5364         if (strlen(driver->help_file)) {
5365                 info = talloc_realloc(mem_ctx, info,
5366                                             struct spoolss_DriverFileInfo,
5367                                             count + 1);
5368                 W_ERROR_HAVE_NO_MEMORY(info);
5369                 result = fill_spoolss_DriverFileInfo(info,
5370                                                      &info[count],
5371                                                      cservername,
5372                                                      driver->help_file,
5373                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5374                                                      0);
5375                 W_ERROR_NOT_OK_RETURN(result);
5376                 count++;
5377         }
5378
5379         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5380                 info = talloc_realloc(mem_ctx, info,
5381                                             struct spoolss_DriverFileInfo,
5382                                             count + 1);
5383                 W_ERROR_HAVE_NO_MEMORY(info);
5384                 result = fill_spoolss_DriverFileInfo(info,
5385                                                      &info[count],
5386                                                      cservername,
5387                                                      driver->dependent_files[i],
5388                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5389                                                      0);
5390                 W_ERROR_NOT_OK_RETURN(result);
5391                 count++;
5392         }
5393
5394         *info_p = info;
5395         *count_p = count;
5396
5397         return WERR_OK;
5398 }
5399
5400 /********************************************************************
5401  * fill a spoolss_DriverInfo101 struct
5402  ********************************************************************/
5403
5404 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5405                                           struct spoolss_DriverInfo101 *r,
5406                                           const struct spoolss_DriverInfo8 *driver,
5407                                           const char *servername)
5408 {
5409         const char *cservername = canon_servername(servername);
5410         WERROR result;
5411
5412         r->version              = driver->version;
5413
5414         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5415         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5416         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5417         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5418
5419         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5420                                                     cservername,
5421                                                     &r->file_info,
5422                                                     &r->file_count);
5423         if (!W_ERROR_IS_OK(result)) {
5424                 return result;
5425         }
5426
5427         FILL_DRIVER_STRING(mem_ctx,
5428                            driver->monitor_name,
5429                            r->monitor_name);
5430
5431         FILL_DRIVER_STRING(mem_ctx,
5432                            driver->default_datatype,
5433                            r->default_datatype);
5434
5435         result = string_array_from_driver_info(mem_ctx,
5436                                                driver->previous_names,
5437                                                &r->previous_names,
5438                                                NULL, NULL, 0);
5439         if (!W_ERROR_IS_OK(result)) {
5440                 return result;
5441         }
5442
5443         r->driver_date          = driver->driver_date;
5444         r->driver_version       = driver->driver_version;
5445
5446         FILL_DRIVER_STRING(mem_ctx,
5447                            driver->manufacturer_name,
5448                            r->manufacturer_name);
5449         FILL_DRIVER_STRING(mem_ctx,
5450                            driver->manufacturer_url,
5451                            r->manufacturer_url);
5452         FILL_DRIVER_STRING(mem_ctx,
5453                            driver->hardware_id,
5454                            r->hardware_id);
5455         FILL_DRIVER_STRING(mem_ctx,
5456                            driver->provider,
5457                            r->provider);
5458
5459         return WERR_OK;
5460 }
5461 #endif
5462 /********************************************************************
5463  ********************************************************************/
5464
5465 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5466                                                   const struct auth_session_info *session_info,
5467                                                   struct messaging_context *msg_ctx,
5468                                                   uint32_t level,
5469                                                   union spoolss_DriverInfo *r,
5470                                                   int snum,
5471                                                   const char *servername,
5472                                                   const char *architecture,
5473                                                   uint32_t version)
5474 {
5475         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5476         struct spoolss_DriverInfo8 *driver;
5477         WERROR result;
5478         struct dcerpc_binding_handle *b;
5479         TALLOC_CTX *tmp_ctx = NULL;
5480
5481         if (level == 101) {
5482                 return WERR_UNKNOWN_LEVEL;
5483         }
5484
5485         tmp_ctx = talloc_new(mem_ctx);
5486         if (!tmp_ctx) {
5487                 return WERR_NOMEM;
5488         }
5489
5490         result = winreg_printer_binding_handle(tmp_ctx,
5491                                                session_info,
5492                                                msg_ctx,
5493                                                &b);
5494         if (!W_ERROR_IS_OK(result)) {
5495                 goto done;
5496         }
5497
5498         result = winreg_get_printer(tmp_ctx, b,
5499                                     lp_const_servicename(snum),
5500                                     &pinfo2);
5501
5502         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5503                 win_errstr(result)));
5504
5505         if (!W_ERROR_IS_OK(result)) {
5506                 result = WERR_INVALID_PRINTER_NAME;
5507                 goto done;
5508         }
5509
5510         result = winreg_get_driver(tmp_ctx, b,
5511                                    architecture,
5512                                    pinfo2->drivername, version, &driver);
5513
5514         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5515                 win_errstr(result)));
5516
5517         if (!W_ERROR_IS_OK(result)) {
5518                 /*
5519                  * Is this a W2k client ?
5520                  */
5521
5522                 if (version < 3) {
5523                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5524                         goto done;
5525                 }
5526
5527                 /* Yes - try again with a WinNT driver. */
5528                 version = 2;
5529                 result = winreg_get_driver(tmp_ctx, b,
5530                                            architecture,
5531                                            pinfo2->drivername,
5532                                            version, &driver);
5533                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5534                         win_errstr(result)));
5535                 if (!W_ERROR_IS_OK(result)) {
5536                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5537                         goto done;
5538                 }
5539         }
5540
5541         /* these are allocated on mem_ctx and not tmp_ctx because they are
5542          * the 'return value' and need to utlive this call */
5543         switch (level) {
5544         case 1:
5545                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5546                 break;
5547         case 2:
5548                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5549                 break;
5550         case 3:
5551                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5552                 break;
5553         case 4:
5554                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5555                 break;
5556         case 5:
5557                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5558                 break;
5559         case 6:
5560                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5561                 break;
5562         case 8:
5563                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5564                 break;
5565 #if 0 /* disabled until marshalling issues are resolved - gd */
5566         case 101:
5567                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5568                 break;
5569 #endif
5570         default:
5571                 result = WERR_UNKNOWN_LEVEL;
5572                 break;
5573         }
5574
5575 done:
5576         talloc_free(tmp_ctx);
5577         return result;
5578 }
5579
5580 /****************************************************************
5581  _spoolss_GetPrinterDriver2
5582 ****************************************************************/
5583
5584 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5585                                   struct spoolss_GetPrinterDriver2 *r)
5586 {
5587         struct printer_handle *printer;
5588         WERROR result;
5589
5590         int snum;
5591
5592         /* that's an [in out] buffer */
5593
5594         if (!r->in.buffer && (r->in.offered != 0)) {
5595                 return WERR_INVALID_PARAM;
5596         }
5597
5598         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5599
5600         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5601                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5602                 return WERR_INVALID_PRINTER_NAME;
5603         }
5604
5605         *r->out.needed = 0;
5606         *r->out.server_major_version = 0;
5607         *r->out.server_minor_version = 0;
5608
5609         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5610                 return WERR_BADFID;
5611         }
5612
5613         result = construct_printer_driver_info_level(p->mem_ctx,
5614                                                      get_session_info_system(),
5615                                                      p->msg_ctx,
5616                                                      r->in.level, r->out.info,
5617                                                      snum, printer->servername,
5618                                                      r->in.architecture,
5619                                                      r->in.client_major_version);
5620         if (!W_ERROR_IS_OK(result)) {
5621                 TALLOC_FREE(r->out.info);
5622                 return result;
5623         }
5624
5625         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5626                                                r->out.info, r->in.level);
5627         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5628
5629         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5630 }
5631
5632
5633 /****************************************************************
5634  _spoolss_StartPagePrinter
5635 ****************************************************************/
5636
5637 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5638                                  struct spoolss_StartPagePrinter *r)
5639 {
5640         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5641
5642         if (!Printer) {
5643                 DEBUG(3,("_spoolss_StartPagePrinter: "
5644                         "Error in startpageprinter printer handle\n"));
5645                 return WERR_BADFID;
5646         }
5647
5648         Printer->page_started = true;
5649         return WERR_OK;
5650 }
5651
5652 /****************************************************************
5653  _spoolss_EndPagePrinter
5654 ****************************************************************/
5655
5656 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5657                                struct spoolss_EndPagePrinter *r)
5658 {
5659         int snum;
5660
5661         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5662
5663         if (!Printer) {
5664                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5665                         OUR_HANDLE(r->in.handle)));
5666                 return WERR_BADFID;
5667         }
5668
5669         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5670                 return WERR_BADFID;
5671
5672         Printer->page_started = false;
5673         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5674
5675         return WERR_OK;
5676 }
5677
5678 /****************************************************************
5679  _spoolss_StartDocPrinter
5680 ****************************************************************/
5681
5682 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5683                                 struct spoolss_StartDocPrinter *r)
5684 {
5685         struct spoolss_DocumentInfo1 *info_1;
5686         int snum;
5687         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5688         WERROR werr;
5689         char *rhost;
5690         int rc;
5691
5692         if (!Printer) {
5693                 DEBUG(2,("_spoolss_StartDocPrinter: "
5694                         "Invalid handle (%s:%u:%u)\n",
5695                         OUR_HANDLE(r->in.handle)));
5696                 return WERR_BADFID;
5697         }
5698
5699         if (Printer->jobid) {
5700                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5701                           "StartDocPrinter called twice! "
5702                           "(existing jobid = %d)\n", Printer->jobid));
5703                 return WERR_INVALID_HANDLE;
5704         }
5705
5706         if (r->in.level != 1) {
5707                 return WERR_UNKNOWN_LEVEL;
5708         }
5709
5710         info_1 = r->in.info.info1;
5711
5712         /*
5713          * a nice thing with NT is it doesn't listen to what you tell it.
5714          * when asked to send _only_ RAW datas, it tries to send datas
5715          * in EMF format.
5716          *
5717          * So I add checks like in NT Server ...
5718          */
5719
5720         if (info_1->datatype) {
5721                 if (strcmp(info_1->datatype, "RAW") != 0) {
5722                         *r->out.job_id = 0;
5723                         return WERR_INVALID_DATATYPE;
5724                 }
5725         }
5726
5727         /* get the share number of the printer */
5728         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5729                 return WERR_BADFID;
5730         }
5731
5732         rc = get_remote_hostname(p->remote_address,
5733                                  &rhost,
5734                                  p->mem_ctx);
5735         if (rc < 0) {
5736                 return WERR_NOMEM;
5737         }
5738         if (strequal(rhost,"UNKNOWN")) {
5739                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5740                                                          p->mem_ctx);
5741                 if (rhost == NULL) {
5742                         return WERR_NOMEM;
5743                 }
5744         }
5745
5746         werr = print_job_start(p->session_info,
5747                                p->msg_ctx,
5748                                rhost,
5749                                snum,
5750                                info_1->document_name,
5751                                info_1->output_file,
5752                                Printer->devmode,
5753                                &Printer->jobid);
5754
5755         /* An error occured in print_job_start() so return an appropriate
5756            NT error code. */
5757
5758         if (!W_ERROR_IS_OK(werr)) {
5759                 return werr;
5760         }
5761
5762         Printer->document_started = true;
5763         *r->out.job_id = Printer->jobid;
5764
5765         return WERR_OK;
5766 }
5767
5768 /****************************************************************
5769  _spoolss_EndDocPrinter
5770 ****************************************************************/
5771
5772 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5773                               struct spoolss_EndDocPrinter *r)
5774 {
5775         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5776         NTSTATUS status;
5777         int snum;
5778
5779         if (!Printer) {
5780                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5781                         OUR_HANDLE(r->in.handle)));
5782                 return WERR_BADFID;
5783         }
5784
5785         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5786                 return WERR_BADFID;
5787         }
5788
5789         Printer->document_started = false;
5790         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5791         if (!NT_STATUS_IS_OK(status)) {
5792                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5793                           "print_job_end failed [%s]\n",
5794                           nt_errstr(status)));
5795         }
5796
5797         Printer->jobid = 0;
5798         return ntstatus_to_werror(status);
5799 }
5800
5801 /****************************************************************
5802  _spoolss_WritePrinter
5803 ****************************************************************/
5804
5805 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5806                              struct spoolss_WritePrinter *r)
5807 {
5808         ssize_t buffer_written;
5809         int snum;
5810         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5811
5812         if (!Printer) {
5813                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5814                         OUR_HANDLE(r->in.handle)));
5815                 *r->out.num_written = r->in._data_size;
5816                 return WERR_BADFID;
5817         }
5818
5819         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5820                 return WERR_BADFID;
5821
5822         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5823         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5824                                                    snum, Printer->jobid,
5825                                                    (const char *)r->in.data.data,
5826                                                    (size_t)r->in._data_size);
5827         if (buffer_written == (ssize_t)-1) {
5828                 *r->out.num_written = 0;
5829                 if (errno == ENOSPC)
5830                         return WERR_NO_SPOOL_SPACE;
5831                 else
5832                         return WERR_ACCESS_DENIED;
5833         }
5834
5835         *r->out.num_written = r->in._data_size;
5836
5837         return WERR_OK;
5838 }
5839
5840 /********************************************************************
5841  * api_spoolss_getprinter
5842  * called from the spoolss dispatcher
5843  *
5844  ********************************************************************/
5845
5846 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5847                               struct pipes_struct *p)
5848 {
5849         const struct auth_session_info *session_info = p->session_info;
5850         int snum;
5851         WERROR errcode = WERR_BADFUNC;
5852         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5853
5854         if (!Printer) {
5855                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5856                         OUR_HANDLE(handle)));
5857                 return WERR_BADFID;
5858         }
5859
5860         if (!get_printer_snum(p, handle, &snum, NULL))
5861                 return WERR_BADFID;
5862
5863         switch (command) {
5864         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5865                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5866                 break;
5867         case SPOOLSS_PRINTER_CONTROL_RESUME:
5868         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5869                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5870                 break;
5871         case SPOOLSS_PRINTER_CONTROL_PURGE:
5872                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5873                 break;
5874         default:
5875                 return WERR_UNKNOWN_LEVEL;
5876         }
5877
5878         return errcode;
5879 }
5880
5881
5882 /****************************************************************
5883  _spoolss_AbortPrinter
5884  * From MSDN: "Deletes printer's spool file if printer is configured
5885  * for spooling"
5886 ****************************************************************/
5887
5888 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5889                              struct spoolss_AbortPrinter *r)
5890 {
5891         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5892         int             snum;
5893         WERROR          errcode = WERR_OK;
5894
5895         if (!Printer) {
5896                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5897                         OUR_HANDLE(r->in.handle)));
5898                 return WERR_BADFID;
5899         }
5900
5901         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5902                 return WERR_BADFID;
5903
5904         if (!Printer->document_started) {
5905                 return WERR_SPL_NO_STARTDOC;
5906         }
5907
5908         errcode = print_job_delete(p->session_info,
5909                                    p->msg_ctx,
5910                                    snum,
5911                                    Printer->jobid);
5912
5913         return errcode;
5914 }
5915
5916 /********************************************************************
5917  * called by spoolss_api_setprinter
5918  * when updating a printer description
5919  ********************************************************************/
5920
5921 static WERROR update_printer_sec(struct policy_handle *handle,
5922                                  struct pipes_struct *p,
5923                                  struct sec_desc_buf *secdesc_ctr)
5924 {
5925         struct spoolss_security_descriptor *new_secdesc = NULL;
5926         struct spoolss_security_descriptor *old_secdesc = NULL;
5927         const char *printer;
5928         WERROR result;
5929         int snum;
5930         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5931         struct dcerpc_binding_handle *b;
5932         TALLOC_CTX *tmp_ctx = NULL;
5933
5934         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5935                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5936                          OUR_HANDLE(handle)));
5937
5938                 result = WERR_BADFID;
5939                 goto done;
5940         }
5941
5942         if (secdesc_ctr == NULL) {
5943                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5944                 result = WERR_INVALID_PARAM;
5945                 goto done;
5946         }
5947         printer = lp_const_servicename(snum);
5948
5949         /* Check the user has permissions to change the security
5950            descriptor.  By experimentation with two NT machines, the user
5951            requires Full Access to the printer to change security
5952            information. */
5953
5954         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5955                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5956                 result = WERR_ACCESS_DENIED;
5957                 goto done;
5958         }
5959
5960         tmp_ctx = talloc_new(p->mem_ctx);
5961         if (!tmp_ctx) {
5962                 return WERR_NOMEM;
5963         }
5964
5965         result = winreg_printer_binding_handle(tmp_ctx,
5966                                                get_session_info_system(),
5967                                                p->msg_ctx,
5968                                                &b);
5969         if (!W_ERROR_IS_OK(result)) {
5970                 goto done;
5971         }
5972
5973         /* NT seems to like setting the security descriptor even though
5974            nothing may have actually changed. */
5975         result = winreg_get_printer_secdesc(tmp_ctx, b,
5976                                             printer,
5977                                             &old_secdesc);
5978         if (!W_ERROR_IS_OK(result)) {
5979                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
5980                 result = WERR_BADFID;
5981                 goto done;
5982         }
5983
5984         if (DEBUGLEVEL >= 10) {
5985                 struct security_acl *the_acl;
5986                 int i;
5987
5988                 the_acl = old_secdesc->dacl;
5989                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5990                            printer, the_acl->num_aces));
5991
5992                 for (i = 0; i < the_acl->num_aces; i++) {
5993                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5994                                            &the_acl->aces[i].trustee),
5995                                   the_acl->aces[i].access_mask));
5996                 }
5997
5998                 the_acl = secdesc_ctr->sd->dacl;
5999
6000                 if (the_acl) {
6001                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6002                                    printer, the_acl->num_aces));
6003
6004                         for (i = 0; i < the_acl->num_aces; i++) {
6005                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6006                                                    &the_acl->aces[i].trustee),
6007                                            the_acl->aces[i].access_mask));
6008                         }
6009                 } else {
6010                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6011                 }
6012         }
6013
6014         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6015         if (new_secdesc == NULL) {
6016                 result = WERR_NOMEM;
6017                 goto done;
6018         }
6019
6020         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6021                 result = WERR_OK;
6022                 goto done;
6023         }
6024
6025         result = winreg_set_printer_secdesc(tmp_ctx, b,
6026                                             printer,
6027                                             new_secdesc);
6028
6029 done:
6030         talloc_free(tmp_ctx);
6031         return result;
6032 }
6033
6034 /********************************************************************
6035  Canonicalize printer info from a client
6036  ********************************************************************/
6037
6038 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6039                              struct spoolss_SetPrinterInfo2 *info2,
6040                              int snum)
6041 {
6042         fstring printername;
6043         const char *p;
6044
6045         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6046                 "portname=%s drivername=%s comment=%s location=%s\n",
6047                 info2->servername, info2->printername, info2->sharename,
6048                 info2->portname, info2->drivername, info2->comment,
6049                 info2->location));
6050
6051         /* we force some elements to "correct" values */
6052         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6053         if (info2->servername == NULL) {
6054                 return false;
6055         }
6056         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6057         if (info2->sharename == NULL) {
6058                 return false;
6059         }
6060
6061         /* check to see if we allow printername != sharename */
6062         if (lp_force_printername(snum)) {
6063                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6064                                         lp_netbios_name(), info2->sharename);
6065         } else {
6066                 /* make sure printername is in \\server\printername format */
6067                 fstrcpy(printername, info2->printername);
6068                 p = printername;
6069                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6070                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6071                                 p++;
6072                 }
6073
6074                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6075                                         lp_netbios_name(), p);
6076         }
6077         if (info2->printername == NULL) {
6078                 return false;
6079         }
6080
6081         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6082         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6083
6084         return true;
6085 }
6086
6087 /****************************************************************************
6088 ****************************************************************************/
6089
6090 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6091 {
6092         char *cmd = lp_addport_cmd();
6093         char *command = NULL;
6094         int ret;
6095         bool is_print_op = false;
6096
6097         if ( !*cmd ) {
6098                 return WERR_ACCESS_DENIED;
6099         }
6100
6101         command = talloc_asprintf(ctx,
6102                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6103         if (!command) {
6104                 return WERR_NOMEM;
6105         }
6106
6107         if ( token )
6108                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6109
6110         DEBUG(10,("Running [%s]\n", command));
6111
6112         /********* BEGIN SePrintOperatorPrivilege **********/
6113
6114         if ( is_print_op )
6115                 become_root();
6116
6117         ret = smbrun(command, NULL);
6118
6119         if ( is_print_op )
6120                 unbecome_root();
6121
6122         /********* END SePrintOperatorPrivilege **********/
6123
6124         DEBUGADD(10,("returned [%d]\n", ret));
6125
6126         TALLOC_FREE(command);
6127
6128         if ( ret != 0 ) {
6129                 return WERR_ACCESS_DENIED;
6130         }
6131
6132         return WERR_OK;
6133 }
6134
6135 /****************************************************************************
6136 ****************************************************************************/
6137
6138 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6139                                    int snum)
6140 {
6141         /*
6142          * As we do not know if we are embedded in the file server process
6143          * or not, we have to pretend that all shares are in use.
6144          */
6145         return true;
6146 }
6147
6148 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6149                              struct spoolss_SetPrinterInfo2 *info2,
6150                              const char *remote_machine,
6151                              struct messaging_context *msg_ctx)
6152 {
6153         char *cmd = lp_addprinter_cmd();
6154         char **qlines;
6155         char *command = NULL;
6156         int numlines;
6157         int ret;
6158         int fd;
6159         bool is_print_op = false;
6160
6161         if (!remote_machine) {
6162                 return false;
6163         }
6164
6165         command = talloc_asprintf(ctx,
6166                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6167                         cmd, info2->printername, info2->sharename,
6168                         info2->portname, info2->drivername,
6169                         info2->location, info2->comment, remote_machine);
6170         if (!command) {
6171                 return false;
6172         }
6173
6174         if ( token )
6175                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6176
6177         DEBUG(10,("Running [%s]\n", command));
6178
6179         /********* BEGIN SePrintOperatorPrivilege **********/
6180
6181         if ( is_print_op )
6182                 become_root();
6183
6184         if ( (ret = smbrun(command, &fd)) == 0 ) {
6185                 /* Tell everyone we updated smb.conf. */
6186                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6187         }
6188
6189         if ( is_print_op )
6190                 unbecome_root();
6191
6192         /********* END SePrintOperatorPrivilege **********/
6193
6194         DEBUGADD(10,("returned [%d]\n", ret));
6195
6196         TALLOC_FREE(command);
6197
6198         if ( ret != 0 ) {
6199                 if (fd != -1)
6200                         close(fd);
6201                 return false;
6202         }
6203
6204         /* reload our services immediately */
6205         become_root();
6206         reload_services(NULL, spoolss_conn_snum_used, false);
6207         unbecome_root();
6208
6209         numlines = 0;
6210         /* Get lines and convert them back to dos-codepage */
6211         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6212         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6213         close(fd);
6214
6215         /* Set the portname to what the script says the portname should be. */
6216         /* but don't require anything to be return from the script exit a good error code */
6217
6218         if (numlines) {
6219                 /* Set the portname to what the script says the portname should be. */
6220                 info2->portname = talloc_strdup(ctx, qlines[0]);
6221                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6222         }
6223
6224         TALLOC_FREE(qlines);
6225         return true;
6226 }
6227
6228 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6229                                const struct auth_session_info *session_info,
6230                                struct messaging_context *msg_ctx,
6231                                int snum,
6232                                struct spoolss_SetPrinterInfo2 *printer,
6233                                struct spoolss_PrinterInfo2 *old_printer)
6234 {
6235         bool force_update = (old_printer == NULL);
6236         const char *dnsdomname;
6237         const char *longname;
6238         const char *uncname;
6239         const char *spooling;
6240         DATA_BLOB buffer;
6241         WERROR result = WERR_OK;
6242         struct dcerpc_binding_handle *b;
6243         TALLOC_CTX *tmp_ctx;
6244         bool ok;
6245
6246         tmp_ctx = talloc_new(mem_ctx);
6247         if (!tmp_ctx) {
6248                 return WERR_NOMEM;
6249         }
6250
6251         result = winreg_printer_binding_handle(tmp_ctx,
6252                                                session_info,
6253                                                msg_ctx,
6254                                                &b);
6255         if (!W_ERROR_IS_OK(result)) {
6256                 goto done;
6257         }
6258
6259         if (printer->drivername != NULL &&
6260             (force_update ||
6261              !strequal(printer->drivername, old_printer->drivername))) {
6262                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6263                 if (!ok) {
6264                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6265                         result = WERR_INVALID_DATA;
6266                         goto done;
6267                 }
6268                 result = winreg_set_printer_dataex(tmp_ctx, b,
6269                                           printer->sharename,
6270                                           SPOOL_DSSPOOLER_KEY,
6271                                           SPOOL_REG_DRIVERNAME,
6272                                           REG_SZ,
6273                                           buffer.data,
6274                                           buffer.length);
6275                 if (!W_ERROR_IS_OK(result)) {
6276                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6277                         goto done;
6278                 }
6279
6280                 if (!force_update) {
6281                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6282                                 printer->drivername));
6283
6284                         notify_printer_driver(server_event_context(), msg_ctx,
6285                                               snum, printer->drivername ?
6286                                               printer->drivername : "");
6287                 }
6288         }
6289
6290         if (printer->comment != NULL &&
6291             (force_update ||
6292              !strequal(printer->comment, old_printer->comment))) {
6293                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6294                 if (!ok) {
6295                         DEBUG(0, ("comment data corrupted\n"));
6296                         result = WERR_INVALID_DATA;
6297                         goto done;
6298                 }
6299                 result = winreg_set_printer_dataex(tmp_ctx, b,
6300                                           printer->sharename,
6301                                           SPOOL_DSSPOOLER_KEY,
6302                                           SPOOL_REG_DESCRIPTION,
6303                                           REG_SZ,
6304                                           buffer.data,
6305                                           buffer.length);
6306                 if (!W_ERROR_IS_OK(result)) {
6307                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6308                         goto done;
6309                 }
6310
6311                 if (!force_update) {
6312                         notify_printer_comment(server_event_context(), msg_ctx,
6313                                                snum, printer->comment ?
6314                                                printer->comment : "");
6315                 }
6316         }
6317
6318         if (printer->sharename != NULL &&
6319             (force_update ||
6320              !strequal(printer->sharename, old_printer->sharename))) {
6321                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6322                 if (!ok) {
6323                         DEBUG(0, ("sharename data corrupted\n"));
6324                         result = WERR_INVALID_DATA;
6325                         goto done;
6326                 }
6327                 result = winreg_set_printer_dataex(tmp_ctx, b,
6328                                           printer->sharename,
6329                                           SPOOL_DSSPOOLER_KEY,
6330                                           SPOOL_REG_PRINTSHARENAME,
6331                                           REG_SZ,
6332                                           buffer.data,
6333                                           buffer.length);
6334                 if (!W_ERROR_IS_OK(result)) {
6335                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6336                         goto done;
6337                 }
6338
6339                 if (!force_update) {
6340                         notify_printer_sharename(server_event_context(),
6341                                                  msg_ctx,
6342                                                  snum, printer->sharename ?
6343                                                  printer->sharename : "");
6344                 }
6345         }
6346
6347         if (printer->printername != NULL &&
6348             (force_update ||
6349              !strequal(printer->printername, old_printer->printername))) {
6350                 const char *p;
6351
6352                 p = strrchr(printer->printername, '\\' );
6353                 if (p != NULL) {
6354                         p++;
6355                 } else {
6356                         p = printer->printername;
6357                 }
6358
6359                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6360                 if (!ok) {
6361                         DEBUG(0, ("printername data corrupted\n"));
6362                         result = WERR_INVALID_DATA;
6363                         goto done;
6364                 }
6365                 result = winreg_set_printer_dataex(tmp_ctx, b,
6366                                           printer->sharename,
6367                                           SPOOL_DSSPOOLER_KEY,
6368                                           SPOOL_REG_PRINTERNAME,
6369                                           REG_SZ,
6370                                           buffer.data,
6371                                           buffer.length);
6372                 if (!W_ERROR_IS_OK(result)) {
6373                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6374                         goto done;
6375                 }
6376
6377                 if (!force_update) {
6378                         notify_printer_printername(server_event_context(),
6379                                                    msg_ctx, snum, p ? p : "");
6380                 }
6381         }
6382
6383         if (printer->portname != NULL &&
6384             (force_update ||
6385              !strequal(printer->portname, old_printer->portname))) {
6386                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6387                 if (!ok) {
6388                         DEBUG(0, ("portname data corrupted\n"));
6389                         result = WERR_INVALID_DATA;
6390                         goto done;
6391                 }
6392                 result = winreg_set_printer_dataex(tmp_ctx, b,
6393                                           printer->sharename,
6394                                           SPOOL_DSSPOOLER_KEY,
6395                                           SPOOL_REG_PORTNAME,
6396                                           REG_SZ,
6397                                           buffer.data,
6398                                           buffer.length);
6399                 if (!W_ERROR_IS_OK(result)) {
6400                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6401                         goto done;
6402                 }
6403
6404                 if (!force_update) {
6405                         notify_printer_port(server_event_context(),
6406                                             msg_ctx, snum, printer->portname ?
6407                                             printer->portname : "");
6408                 }
6409         }
6410
6411         if (printer->location != NULL &&
6412             (force_update ||
6413              !strequal(printer->location, old_printer->location))) {
6414                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6415                 if (!ok) {
6416                         DEBUG(0, ("location data corrupted\n"));
6417                         result = WERR_INVALID_DATA;
6418                         goto done;
6419                 }
6420                 result = winreg_set_printer_dataex(tmp_ctx, b,
6421                                           printer->sharename,
6422                                           SPOOL_DSSPOOLER_KEY,
6423                                           SPOOL_REG_LOCATION,
6424                                           REG_SZ,
6425                                           buffer.data,
6426                                           buffer.length);
6427                 if (!W_ERROR_IS_OK(result)) {
6428                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6429                         goto done;
6430                 }
6431
6432                 if (!force_update) {
6433                         notify_printer_location(server_event_context(),
6434                                                 msg_ctx, snum,
6435                                                 printer->location ?
6436                                                 printer->location : "");
6437                 }
6438         }
6439
6440         if (printer->sepfile != NULL &&
6441             (force_update ||
6442              !strequal(printer->sepfile, old_printer->sepfile))) {
6443                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6444                 if (!ok) {
6445                         DEBUG(0, ("sepfile data corrupted\n"));
6446                         result = WERR_INVALID_DATA;
6447                         goto done;
6448                 }
6449                 result = winreg_set_printer_dataex(tmp_ctx, b,
6450                                           printer->sharename,
6451                                           SPOOL_DSSPOOLER_KEY,
6452                                           SPOOL_REG_PRINTSEPARATORFILE,
6453                                           REG_SZ,
6454                                           buffer.data,
6455                                           buffer.length);
6456                 if (!W_ERROR_IS_OK(result)) {
6457                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6458                         goto done;
6459                 }
6460
6461                 if (!force_update) {
6462                         notify_printer_sepfile(server_event_context(),
6463                                                msg_ctx, snum,
6464                                                printer->sepfile ?
6465                                                printer->sepfile : "");
6466                 }
6467         }
6468
6469         if (printer->starttime != 0 &&
6470             (force_update ||
6471              printer->starttime != old_printer->starttime)) {
6472                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6473                 SIVAL(buffer.data, 0, printer->starttime);
6474                 result = winreg_set_printer_dataex(tmp_ctx, b,
6475                                           printer->sharename,
6476                                           SPOOL_DSSPOOLER_KEY,
6477                                           SPOOL_REG_PRINTSTARTTIME,
6478                                           REG_DWORD,
6479                                           buffer.data,
6480                                           buffer.length);
6481                 if (!W_ERROR_IS_OK(result)) {
6482                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6483                         goto done;
6484                 }
6485         }
6486
6487         if (printer->untiltime != 0 &&
6488             (force_update ||
6489              printer->untiltime != old_printer->untiltime)) {
6490                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6491                 SIVAL(buffer.data, 0, printer->untiltime);
6492                 result = winreg_set_printer_dataex(tmp_ctx, b,
6493                                           printer->sharename,
6494                                           SPOOL_DSSPOOLER_KEY,
6495                                           SPOOL_REG_PRINTENDTIME,
6496                                           REG_DWORD,
6497                                           buffer.data,
6498                                           buffer.length);
6499                 if (!W_ERROR_IS_OK(result)) {
6500                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6501                         goto done;
6502                 }
6503         }
6504
6505         if (force_update || printer->priority != old_printer->priority) {
6506                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6507                 SIVAL(buffer.data, 0, printer->priority);
6508                 result = winreg_set_printer_dataex(tmp_ctx, b,
6509                                           printer->sharename,
6510                                           SPOOL_DSSPOOLER_KEY,
6511                                           SPOOL_REG_PRIORITY,
6512                                           REG_DWORD,
6513                                           buffer.data,
6514                                           buffer.length);
6515                 if (!W_ERROR_IS_OK(result)) {
6516                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6517                         goto done;
6518                 }
6519         }
6520
6521         if (force_update || printer->attributes != old_printer->attributes) {
6522                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6523                 SIVAL(buffer.data, 0, (printer->attributes &
6524                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6525                 result = winreg_set_printer_dataex(tmp_ctx, b,
6526                                           printer->sharename,
6527                                           SPOOL_DSSPOOLER_KEY,
6528                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6529                                           REG_DWORD,
6530                                           buffer.data,
6531                                           buffer.length);
6532                 if (!W_ERROR_IS_OK(result)) {
6533                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6534                         goto done;
6535                 }
6536
6537                 switch (printer->attributes & 0x3) {
6538                         case 0:
6539                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6540                                 break;
6541                         case 1:
6542                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6543                                 break;
6544                         case 2:
6545                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6546                                 break;
6547                         default:
6548                                 spooling = "unknown";
6549                 }
6550                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6551                 if (!ok) {
6552                         DEBUG(0, ("printSpooling data corrupted\n"));
6553                         result = WERR_INVALID_DATA;
6554                         goto done;
6555                 }
6556                 winreg_set_printer_dataex(tmp_ctx, b,
6557                                           printer->sharename,
6558                                           SPOOL_DSSPOOLER_KEY,
6559                                           SPOOL_REG_PRINTSPOOLING,
6560                                           REG_SZ,
6561                                           buffer.data,
6562                                           buffer.length);
6563         }
6564
6565         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6566         if (!ok) {
6567                 DEBUG(0, ("shortServerName data corrupted\n"));
6568                 result = WERR_INVALID_DATA;
6569                 goto done;
6570         }
6571         result = winreg_set_printer_dataex(tmp_ctx, b,
6572                                   printer->sharename,
6573                                   SPOOL_DSSPOOLER_KEY,
6574                                   SPOOL_REG_SHORTSERVERNAME,
6575                                   REG_SZ,
6576                                   buffer.data,
6577                                   buffer.length);
6578         if (!W_ERROR_IS_OK(result)) {
6579                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6580                 goto done;
6581         }
6582
6583         dnsdomname = get_mydnsfullname();
6584         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6585                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6586         } else {
6587                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6588         }
6589         if (longname == NULL) {
6590                 result = WERR_NOMEM;
6591                 goto done;
6592         }
6593
6594         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6595         if (!ok) {
6596                 DEBUG(0, ("longname data corrupted\n"));
6597                 result = WERR_INVALID_DATA;
6598                 goto done;
6599         }
6600         result = winreg_set_printer_dataex(tmp_ctx, b,
6601                                            printer->sharename,
6602                                            SPOOL_DSSPOOLER_KEY,
6603                                            SPOOL_REG_SERVERNAME,
6604                                            REG_SZ,
6605                                            buffer.data,
6606                                            buffer.length);
6607         if (!W_ERROR_IS_OK(result)) {
6608                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6609                 goto done;
6610         }
6611
6612         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6613                                   lp_netbios_name(), printer->sharename);
6614         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6615         if (!ok) {
6616                 DEBUG(0, ("uncName data corrupted\n"));
6617                 result = WERR_INVALID_DATA;
6618                 goto done;
6619         }
6620         result = winreg_set_printer_dataex(tmp_ctx, b,
6621                                   printer->sharename,
6622                                   SPOOL_DSSPOOLER_KEY,
6623                                   SPOOL_REG_UNCNAME,
6624                                   REG_SZ,
6625                                   buffer.data,
6626                                   buffer.length);
6627         if (!W_ERROR_IS_OK(result)) {
6628                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6629                 goto done;
6630         }
6631
6632 done:
6633         talloc_free(tmp_ctx);
6634         return result;
6635 }
6636
6637 /********************************************************************
6638  * Called by spoolss_api_setprinter
6639  * when updating a printer description.
6640  ********************************************************************/
6641
6642 static WERROR update_printer(struct pipes_struct *p,
6643                              struct policy_handle *handle,
6644                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6645                              struct spoolss_DeviceMode *devmode)
6646 {
6647         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6648         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6649         struct spoolss_PrinterInfo2 *old_printer;
6650         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6651         int snum;
6652         WERROR result = WERR_OK;
6653         TALLOC_CTX *tmp_ctx;
6654         struct dcerpc_binding_handle *b;
6655
6656         DEBUG(8,("update_printer\n"));
6657
6658         tmp_ctx = talloc_new(p->mem_ctx);
6659         if (tmp_ctx == NULL) {
6660                 return WERR_NOMEM;
6661         }
6662
6663         if (!Printer) {
6664                 result = WERR_BADFID;
6665                 goto done;
6666         }
6667
6668         if (!get_printer_snum(p, handle, &snum, NULL)) {
6669                 result = WERR_BADFID;
6670                 goto done;
6671         }
6672
6673         result = winreg_printer_binding_handle(tmp_ctx,
6674                                                get_session_info_system(),
6675                                                p->msg_ctx,
6676                                                &b);
6677         if (!W_ERROR_IS_OK(result)) {
6678                 goto done;
6679         }
6680
6681         result = winreg_get_printer(tmp_ctx, b,
6682                                     lp_const_servicename(snum),
6683                                     &old_printer);
6684         if (!W_ERROR_IS_OK(result)) {
6685                 result = WERR_BADFID;
6686                 goto done;
6687         }
6688
6689         /* Do sanity check on the requested changes for Samba */
6690         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6691                 result = WERR_INVALID_PARAM;
6692                 goto done;
6693         }
6694
6695         /* FIXME!!! If the driver has changed we really should verify that
6696            it is installed before doing much else   --jerry */
6697
6698         /* Check calling user has permission to update printer description */
6699         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6700                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6701                 result = WERR_ACCESS_DENIED;
6702                 goto done;
6703         }
6704
6705         /* Call addprinter hook */
6706         /* Check changes to see if this is really needed */
6707
6708         if (*lp_addprinter_cmd() &&
6709                         (!strequal(printer->drivername, old_printer->drivername) ||
6710                          !strequal(printer->comment, old_printer->comment) ||
6711                          !strequal(printer->portname, old_printer->portname) ||
6712                          !strequal(printer->location, old_printer->location)) )
6713         {
6714                 char *raddr;
6715
6716                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6717                                                          p->mem_ctx);
6718                 if (raddr == NULL) {
6719                         return WERR_NOMEM;
6720                 }
6721
6722                 /* add_printer_hook() will call reload_services() */
6723                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6724                                       printer, raddr,
6725                                       p->msg_ctx)) {
6726                         result = WERR_ACCESS_DENIED;
6727                         goto done;
6728                 }
6729         }
6730
6731         result = update_dsspooler(tmp_ctx,
6732                                   get_session_info_system(),
6733                                   p->msg_ctx,
6734                                   snum,
6735                                   printer,
6736                                   old_printer);
6737         if (!W_ERROR_IS_OK(result)) {
6738                 goto done;
6739         }
6740
6741         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6742
6743         if (devmode == NULL) {
6744                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6745         }
6746         result = winreg_update_printer(tmp_ctx, b,
6747                                        printer->sharename,
6748                                        printer_mask,
6749                                        printer,
6750                                        devmode,
6751                                        NULL);
6752
6753 done:
6754         talloc_free(tmp_ctx);
6755
6756         return result;
6757 }
6758
6759 /****************************************************************************
6760 ****************************************************************************/
6761 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6762                                            struct policy_handle *handle,
6763                                            struct spoolss_SetPrinterInfo7 *info7)
6764 {
6765 #ifdef HAVE_ADS
6766         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6767         WERROR result;
6768         int snum;
6769         struct printer_handle *Printer;
6770
6771         if ( lp_security() != SEC_ADS ) {
6772                 return WERR_UNKNOWN_LEVEL;
6773         }
6774
6775         Printer = find_printer_index_by_hnd(p, handle);
6776
6777         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6778
6779         if (!Printer)
6780                 return WERR_BADFID;
6781
6782         if (!get_printer_snum(p, handle, &snum, NULL))
6783                 return WERR_BADFID;
6784
6785         result = winreg_get_printer_internal(p->mem_ctx,
6786                                     get_session_info_system(),
6787                                     p->msg_ctx,
6788                                     lp_servicename(snum),
6789                                     &pinfo2);
6790         if (!W_ERROR_IS_OK(result)) {
6791                 return WERR_BADFID;
6792         }
6793
6794         nt_printer_publish(pinfo2,
6795                            get_session_info_system(),
6796                            p->msg_ctx,
6797                            pinfo2,
6798                            info7->action);
6799
6800         TALLOC_FREE(pinfo2);
6801         return WERR_OK;
6802 #else
6803         return WERR_UNKNOWN_LEVEL;
6804 #endif
6805 }
6806
6807 /********************************************************************
6808  ********************************************************************/
6809
6810 static WERROR update_printer_devmode(struct pipes_struct *p,
6811                                      struct policy_handle *handle,
6812                                      struct spoolss_DeviceMode *devmode)
6813 {
6814         int snum;
6815         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6816         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6817
6818         DEBUG(8,("update_printer_devmode\n"));
6819
6820         if (!Printer) {
6821                 return WERR_BADFID;
6822         }
6823
6824         if (!get_printer_snum(p, handle, &snum, NULL)) {
6825                 return WERR_BADFID;
6826         }
6827
6828         /* Check calling user has permission to update printer description */
6829         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6830                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6831                 return WERR_ACCESS_DENIED;
6832         }
6833
6834         return winreg_update_printer_internal(p->mem_ctx,
6835                                      get_session_info_system(),
6836                                      p->msg_ctx,
6837                                      lp_const_servicename(snum),
6838                                      info2_mask,
6839                                      NULL,
6840                                      devmode,
6841                                      NULL);
6842 }
6843
6844
6845 /****************************************************************
6846  _spoolss_SetPrinter
6847 ****************************************************************/
6848
6849 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6850                            struct spoolss_SetPrinter *r)
6851 {
6852         WERROR result;
6853
6854         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6855
6856         if (!Printer) {
6857                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6858                         OUR_HANDLE(r->in.handle)));
6859                 return WERR_BADFID;
6860         }
6861
6862         /* check the level */
6863         switch (r->in.info_ctr->level) {
6864                 case 0:
6865                         return control_printer(r->in.handle, r->in.command, p);
6866                 case 2:
6867                         result = update_printer(p, r->in.handle,
6868                                                 r->in.info_ctr,
6869                                                 r->in.devmode_ctr->devmode);
6870                         if (!W_ERROR_IS_OK(result))
6871                                 return result;
6872                         if (r->in.secdesc_ctr->sd)
6873                                 result = update_printer_sec(r->in.handle, p,
6874                                                             r->in.secdesc_ctr);
6875                         return result;
6876                 case 3:
6877                         return update_printer_sec(r->in.handle, p,
6878                                                   r->in.secdesc_ctr);
6879                 case 7:
6880                         return publish_or_unpublish_printer(p, r->in.handle,
6881                                                             r->in.info_ctr->info.info7);
6882                 case 8:
6883                         return update_printer_devmode(p, r->in.handle,
6884                                                       r->in.devmode_ctr->devmode);
6885                 default:
6886                         return WERR_UNKNOWN_LEVEL;
6887         }
6888 }
6889
6890 /****************************************************************
6891  _spoolss_FindClosePrinterNotify
6892 ****************************************************************/
6893
6894 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6895                                        struct spoolss_FindClosePrinterNotify *r)
6896 {
6897         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6898
6899         if (!Printer) {
6900                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6901                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6902                 return WERR_BADFID;
6903         }
6904
6905         if (Printer->notify.cli_chan != NULL &&
6906             Printer->notify.cli_chan->active_connections > 0) {
6907                 int snum = -1;
6908
6909                 if (Printer->printer_type == SPLHND_PRINTER) {
6910                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6911                                 return WERR_BADFID;
6912                         }
6913                 }
6914
6915                 srv_spoolss_replycloseprinter(snum, Printer);
6916         }
6917
6918         Printer->notify.flags=0;
6919         Printer->notify.options=0;
6920         Printer->notify.localmachine[0]='\0';
6921         Printer->notify.printerlocal=0;
6922         TALLOC_FREE(Printer->notify.option);
6923
6924         return WERR_OK;
6925 }
6926
6927 /****************************************************************
6928  _spoolss_AddJob
6929 ****************************************************************/
6930
6931 WERROR _spoolss_AddJob(struct pipes_struct *p,
6932                        struct spoolss_AddJob *r)
6933 {
6934         if (!r->in.buffer && (r->in.offered != 0)) {
6935                 return WERR_INVALID_PARAM;
6936         }
6937
6938         /* this is what a NT server returns for AddJob. AddJob must fail on
6939          * non-local printers */
6940
6941         if (r->in.level != 1) {
6942                 return WERR_UNKNOWN_LEVEL;
6943         }
6944
6945         return WERR_INVALID_PARAM;
6946 }
6947
6948 /****************************************************************************
6949 fill_job_info1
6950 ****************************************************************************/
6951
6952 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6953                              struct spoolss_JobInfo1 *r,
6954                              const print_queue_struct *queue,
6955                              int position, int snum,
6956                              struct spoolss_PrinterInfo2 *pinfo2)
6957 {
6958         struct tm *t;
6959
6960         t = gmtime(&queue->time);
6961
6962         r->job_id               = queue->sysjob;
6963
6964         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
6965         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6966         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6967         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6968         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6969         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6970         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6971         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6972         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6973         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6974         r->text_status          = talloc_strdup(mem_ctx, "");
6975         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6976
6977         r->status               = nt_printj_status(queue->status);
6978         r->priority             = queue->priority;
6979         r->position             = position;
6980         r->total_pages          = queue->page_count;
6981         r->pages_printed        = 0; /* ??? */
6982
6983         init_systemtime(&r->submitted, t);
6984
6985         return WERR_OK;
6986 }
6987
6988 /****************************************************************************
6989 fill_job_info2
6990 ****************************************************************************/
6991
6992 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6993                              struct spoolss_JobInfo2 *r,
6994                              const print_queue_struct *queue,
6995                              int position, int snum,
6996                              struct spoolss_PrinterInfo2 *pinfo2,
6997                              struct spoolss_DeviceMode *devmode)
6998 {
6999         struct tm *t;
7000
7001         t = gmtime(&queue->time);
7002
7003         r->job_id               = queue->sysjob;
7004
7005         r->printer_name         = talloc_strdup(mem_ctx, lp_servicename(snum));
7006         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7007         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7008         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7009         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7010         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7011         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7012         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7013         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7014         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7015         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7016         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7017         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7018         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7019         r->parameters           = talloc_strdup(mem_ctx, "");
7020         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7021         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7022         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7023
7024         r->devmode              = devmode;
7025
7026         r->text_status          = talloc_strdup(mem_ctx, "");
7027         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7028
7029         r->secdesc              = NULL;
7030
7031         r->status               = nt_printj_status(queue->status);
7032         r->priority             = queue->priority;
7033         r->position             = position;
7034         r->start_time           = 0;
7035         r->until_time           = 0;
7036         r->total_pages          = queue->page_count;
7037         r->size                 = queue->size;
7038         init_systemtime(&r->submitted, t);
7039         r->time                 = 0;
7040         r->pages_printed        = 0; /* ??? */
7041
7042         return WERR_OK;
7043 }
7044
7045 /****************************************************************************
7046 fill_job_info3
7047 ****************************************************************************/
7048
7049 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7050                              struct spoolss_JobInfo3 *r,
7051                              const print_queue_struct *queue,
7052                              const print_queue_struct *next_queue,
7053                              int position, int snum,
7054                              struct spoolss_PrinterInfo2 *pinfo2)
7055 {
7056         r->job_id               = queue->sysjob;
7057         r->next_job_id          = 0;
7058         if (next_queue) {
7059                 r->next_job_id  = next_queue->sysjob;
7060         }
7061         r->reserved             = 0;
7062
7063         return WERR_OK;
7064 }
7065
7066 /****************************************************************************
7067  Enumjobs at level 1.
7068 ****************************************************************************/
7069
7070 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7071                               const print_queue_struct *queue,
7072                               uint32_t num_queues, int snum,
7073                               struct spoolss_PrinterInfo2 *pinfo2,
7074                               union spoolss_JobInfo **info_p,
7075                               uint32_t *count)
7076 {
7077         union spoolss_JobInfo *info;
7078         int i;
7079         WERROR result = WERR_OK;
7080
7081         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7082         W_ERROR_HAVE_NO_MEMORY(info);
7083
7084         *count = num_queues;
7085
7086         for (i=0; i<*count; i++) {
7087                 result = fill_job_info1(info,
7088                                         &info[i].info1,
7089                                         &queue[i],
7090                                         i,
7091                                         snum,
7092                                         pinfo2);
7093                 if (!W_ERROR_IS_OK(result)) {
7094                         goto out;
7095                 }
7096         }
7097
7098  out:
7099         if (!W_ERROR_IS_OK(result)) {
7100                 TALLOC_FREE(info);
7101                 *count = 0;
7102                 return result;
7103         }
7104
7105         *info_p = info;
7106
7107         return WERR_OK;
7108 }
7109
7110 /****************************************************************************
7111  Enumjobs at level 2.
7112 ****************************************************************************/
7113
7114 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7115                               const print_queue_struct *queue,
7116                               uint32_t num_queues, int snum,
7117                               struct spoolss_PrinterInfo2 *pinfo2,
7118                               union spoolss_JobInfo **info_p,
7119                               uint32_t *count)
7120 {
7121         union spoolss_JobInfo *info;
7122         int i;
7123         WERROR result = WERR_OK;
7124
7125         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7126         W_ERROR_HAVE_NO_MEMORY(info);
7127
7128         *count = num_queues;
7129
7130         for (i=0; i<*count; i++) {
7131                 struct spoolss_DeviceMode *devmode;
7132
7133                 result = spoolss_create_default_devmode(info,
7134                                                         pinfo2->printername,
7135                                                         &devmode);
7136                 if (!W_ERROR_IS_OK(result)) {
7137                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7138                         goto out;
7139                 }
7140
7141                 result = fill_job_info2(info,
7142                                         &info[i].info2,
7143                                         &queue[i],
7144                                         i,
7145                                         snum,
7146                                         pinfo2,
7147                                         devmode);
7148                 if (!W_ERROR_IS_OK(result)) {
7149                         goto out;
7150                 }
7151         }
7152
7153  out:
7154         if (!W_ERROR_IS_OK(result)) {
7155                 TALLOC_FREE(info);
7156                 *count = 0;
7157                 return result;
7158         }
7159
7160         *info_p = info;
7161
7162         return WERR_OK;
7163 }
7164
7165 /****************************************************************************
7166  Enumjobs at level 3.
7167 ****************************************************************************/
7168
7169 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7170                               const print_queue_struct *queue,
7171                               uint32_t num_queues, int snum,
7172                               struct spoolss_PrinterInfo2 *pinfo2,
7173                               union spoolss_JobInfo **info_p,
7174                               uint32_t *count)
7175 {
7176         union spoolss_JobInfo *info;
7177         int i;
7178         WERROR result = WERR_OK;
7179
7180         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7181         W_ERROR_HAVE_NO_MEMORY(info);
7182
7183         *count = num_queues;
7184
7185         for (i=0; i<*count; i++) {
7186                 const print_queue_struct *next_queue = NULL;
7187
7188                 if (i+1 < *count) {
7189                         next_queue = &queue[i+1];
7190                 }
7191
7192                 result = fill_job_info3(info,
7193                                         &info[i].info3,
7194                                         &queue[i],
7195                                         next_queue,
7196                                         i,
7197                                         snum,
7198                                         pinfo2);
7199                 if (!W_ERROR_IS_OK(result)) {
7200                         goto out;
7201                 }
7202         }
7203
7204  out:
7205         if (!W_ERROR_IS_OK(result)) {
7206                 TALLOC_FREE(info);
7207                 *count = 0;
7208                 return result;
7209         }
7210
7211         *info_p = info;
7212
7213         return WERR_OK;
7214 }
7215
7216 /****************************************************************
7217  _spoolss_EnumJobs
7218 ****************************************************************/
7219
7220 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7221                          struct spoolss_EnumJobs *r)
7222 {
7223         WERROR result;
7224         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7225         int snum;
7226         print_status_struct prt_status;
7227         print_queue_struct *queue = NULL;
7228         uint32_t count;
7229
7230         /* that's an [in out] buffer */
7231
7232         if (!r->in.buffer && (r->in.offered != 0)) {
7233                 return WERR_INVALID_PARAM;
7234         }
7235
7236         DEBUG(4,("_spoolss_EnumJobs\n"));
7237
7238         *r->out.needed = 0;
7239         *r->out.count = 0;
7240         *r->out.info = NULL;
7241
7242         /* lookup the printer snum and tdb entry */
7243
7244         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7245                 return WERR_BADFID;
7246         }
7247
7248         result = winreg_get_printer_internal(p->mem_ctx,
7249                                     get_session_info_system(),
7250                                     p->msg_ctx,
7251                                     lp_const_servicename(snum),
7252                                     &pinfo2);
7253         if (!W_ERROR_IS_OK(result)) {
7254                 return result;
7255         }
7256
7257         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7258         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7259                 count, prt_status.status, prt_status.message));
7260
7261         if (count == 0) {
7262                 SAFE_FREE(queue);
7263                 TALLOC_FREE(pinfo2);
7264                 return WERR_OK;
7265         }
7266
7267         switch (r->in.level) {
7268         case 1:
7269                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7270                                          pinfo2, r->out.info, r->out.count);
7271                 break;
7272         case 2:
7273                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7274                                          pinfo2, r->out.info, r->out.count);
7275                 break;
7276         case 3:
7277                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7278                                          pinfo2, r->out.info, r->out.count);
7279                 break;
7280         default:
7281                 result = WERR_UNKNOWN_LEVEL;
7282                 break;
7283         }
7284
7285         SAFE_FREE(queue);
7286         TALLOC_FREE(pinfo2);
7287
7288         if (!W_ERROR_IS_OK(result)) {
7289                 return result;
7290         }
7291
7292         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7293                                                      spoolss_EnumJobs,
7294                                                      *r->out.info, r->in.level,
7295                                                      *r->out.count);
7296         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7297         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7298
7299         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7300 }
7301
7302 /****************************************************************
7303  _spoolss_ScheduleJob
7304 ****************************************************************/
7305
7306 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7307                             struct spoolss_ScheduleJob *r)
7308 {
7309         return WERR_OK;
7310 }
7311
7312 /****************************************************************
7313 ****************************************************************/
7314
7315 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7316                                struct messaging_context *msg_ctx,
7317                                const char *printer_name,
7318                                uint32_t job_id,
7319                                struct spoolss_SetJobInfo1 *r)
7320 {
7321         char *old_doc_name;
7322
7323         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7324                 return WERR_BADFID;
7325         }
7326
7327         if (strequal(old_doc_name, r->document_name)) {
7328                 return WERR_OK;
7329         }
7330
7331         if (!print_job_set_name(server_event_context(), msg_ctx,
7332                                 printer_name, job_id, r->document_name)) {
7333                 return WERR_BADFID;
7334         }
7335
7336         return WERR_OK;
7337 }
7338
7339 /****************************************************************
7340  _spoolss_SetJob
7341 ****************************************************************/
7342
7343 WERROR _spoolss_SetJob(struct pipes_struct *p,
7344                        struct spoolss_SetJob *r)
7345 {
7346         const struct auth_session_info *session_info = p->session_info;
7347         int snum;
7348         WERROR errcode = WERR_BADFUNC;
7349
7350         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7351                 return WERR_BADFID;
7352         }
7353
7354         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7355                 return WERR_INVALID_PRINTER_NAME;
7356         }
7357
7358         switch (r->in.command) {
7359         case SPOOLSS_JOB_CONTROL_CANCEL:
7360         case SPOOLSS_JOB_CONTROL_DELETE:
7361                 errcode = print_job_delete(session_info, p->msg_ctx,
7362                                            snum, r->in.job_id);
7363                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7364                         errcode = WERR_OK;
7365                 }
7366                 break;
7367         case SPOOLSS_JOB_CONTROL_PAUSE:
7368                 errcode = print_job_pause(session_info, p->msg_ctx,
7369                                           snum, r->in.job_id);
7370                 break;
7371         case SPOOLSS_JOB_CONTROL_RESTART:
7372         case SPOOLSS_JOB_CONTROL_RESUME:
7373                 errcode = print_job_resume(session_info, p->msg_ctx,
7374                                            snum, r->in.job_id);
7375                 break;
7376         case 0:
7377                 errcode = WERR_OK;
7378                 break;
7379         default:
7380                 return WERR_UNKNOWN_LEVEL;
7381         }
7382
7383         if (!W_ERROR_IS_OK(errcode)) {
7384                 return errcode;
7385         }
7386
7387         if (r->in.ctr == NULL) {
7388                 return errcode;
7389         }
7390
7391         switch (r->in.ctr->level) {
7392         case 1:
7393                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7394                                            lp_const_servicename(snum),
7395                                            r->in.job_id,
7396                                            r->in.ctr->info.info1);
7397                 break;
7398         case 2:
7399         case 3:
7400         case 4:
7401         default:
7402                 return WERR_UNKNOWN_LEVEL;
7403         }
7404
7405         return errcode;
7406 }
7407
7408 /****************************************************************************
7409  Enumerates all printer drivers by level and architecture.
7410 ****************************************************************************/
7411
7412 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7413                                                        const struct auth_session_info *session_info,
7414                                                        struct messaging_context *msg_ctx,
7415                                                        const char *servername,
7416                                                        const char *architecture,
7417                                                        uint32_t level,
7418                                                        union spoolss_DriverInfo **info_p,
7419                                                        uint32_t *count_p)
7420 {
7421         int i;
7422         uint32_t version;
7423         struct spoolss_DriverInfo8 *driver;
7424         union spoolss_DriverInfo *info = NULL;
7425         uint32_t count = 0;
7426         WERROR result = WERR_OK;
7427         uint32_t num_drivers;
7428         const char **drivers;
7429         struct dcerpc_binding_handle *b;
7430         TALLOC_CTX *tmp_ctx = NULL;
7431
7432         *count_p = 0;
7433         *info_p = NULL;
7434
7435         tmp_ctx = talloc_new(mem_ctx);
7436         if (!tmp_ctx) {
7437                 return WERR_NOMEM;
7438         }
7439
7440         result = winreg_printer_binding_handle(tmp_ctx,
7441                                                session_info,
7442                                                msg_ctx,
7443                                                &b);
7444         if (!W_ERROR_IS_OK(result)) {
7445                 goto out;
7446         }
7447
7448         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7449                 result = winreg_get_driver_list(tmp_ctx, b,
7450                                                 architecture, version,
7451                                                 &num_drivers, &drivers);
7452                 if (!W_ERROR_IS_OK(result)) {
7453                         goto out;
7454                 }
7455                 DEBUG(4, ("we have:[%d] drivers in environment"
7456                           " [%s] and version [%d]\n",
7457                           num_drivers, architecture, version));
7458
7459                 if (num_drivers != 0) {
7460                         info = talloc_realloc(tmp_ctx, info,
7461                                                     union spoolss_DriverInfo,
7462                                                     count + num_drivers);
7463                         if (!info) {
7464                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7465                                         "failed to enlarge driver info buffer!\n"));
7466                                 result = WERR_NOMEM;
7467                                 goto out;
7468                         }
7469                 }
7470
7471                 for (i = 0; i < num_drivers; i++) {
7472                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7473
7474                         result = winreg_get_driver(tmp_ctx, b,
7475                                                    architecture, drivers[i],
7476                                                    version, &driver);
7477                         if (!W_ERROR_IS_OK(result)) {
7478                                 goto out;
7479                         }
7480
7481                         switch (level) {
7482                         case 1:
7483                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7484                                                                    driver, servername);
7485                                 break;
7486                         case 2:
7487                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7488                                                                    driver, servername);
7489                                 break;
7490                         case 3:
7491                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7492                                                                    driver, servername);
7493                                 break;
7494                         case 4:
7495                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7496                                                                    driver, servername);
7497                                 break;
7498                         case 5:
7499                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7500                                                                    driver, servername);
7501                                 break;
7502                         case 6:
7503                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7504                                                                    driver, servername);
7505                                 break;
7506                         case 8:
7507                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7508                                                                    driver, servername);
7509                                 break;
7510                         default:
7511                                 result = WERR_UNKNOWN_LEVEL;
7512                                 break;
7513                         }
7514
7515                         TALLOC_FREE(driver);
7516
7517                         if (!W_ERROR_IS_OK(result)) {
7518                                 goto out;
7519                         }
7520                 }
7521
7522                 count += num_drivers;
7523                 TALLOC_FREE(drivers);
7524         }
7525
7526 out:
7527         if (W_ERROR_IS_OK(result)) {
7528                 *info_p = talloc_move(mem_ctx, &info);
7529                 *count_p = count;
7530         }
7531
7532         talloc_free(tmp_ctx);
7533         return result;
7534 }
7535
7536 /****************************************************************************
7537  Enumerates all printer drivers by level.
7538 ****************************************************************************/
7539
7540 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7541                                        const struct auth_session_info *session_info,
7542                                        struct messaging_context *msg_ctx,
7543                                        const char *servername,
7544                                        const char *architecture,
7545                                        uint32_t level,
7546                                        union spoolss_DriverInfo **info_p,
7547                                        uint32_t *count_p)
7548 {
7549         uint32_t a,i;
7550         WERROR result = WERR_OK;
7551
7552         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7553
7554                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7555
7556                         union spoolss_DriverInfo *info = NULL;
7557                         uint32_t count = 0;
7558
7559                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7560                                                                           session_info,
7561                                                                           msg_ctx,
7562                                                                           servername,
7563                                                                           archi_table[a].long_archi,
7564                                                                           level,
7565                                                                           &info,
7566                                                                           &count);
7567                         if (!W_ERROR_IS_OK(result)) {
7568                                 continue;
7569                         }
7570
7571                         for (i=0; i < count; i++) {
7572                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7573                                              info[i], info_p, count_p);
7574                         }
7575                 }
7576
7577                 return result;
7578         }
7579
7580         return enumprinterdrivers_level_by_architecture(mem_ctx,
7581                                                         session_info,
7582                                                         msg_ctx,
7583                                                         servername,
7584                                                         architecture,
7585                                                         level,
7586                                                         info_p,
7587                                                         count_p);
7588 }
7589
7590 /****************************************************************
7591  _spoolss_EnumPrinterDrivers
7592 ****************************************************************/
7593
7594 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7595                                    struct spoolss_EnumPrinterDrivers *r)
7596 {
7597         const char *cservername;
7598         WERROR result;
7599
7600         /* that's an [in out] buffer */
7601
7602         if (!r->in.buffer && (r->in.offered != 0)) {
7603                 return WERR_INVALID_PARAM;
7604         }
7605
7606         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7607
7608         *r->out.needed = 0;
7609         *r->out.count = 0;
7610         *r->out.info = NULL;
7611
7612         cservername = canon_servername(r->in.server);
7613
7614         if (!is_myname_or_ipaddr(cservername)) {
7615                 return WERR_UNKNOWN_PRINTER_DRIVER;
7616         }
7617
7618         result = enumprinterdrivers_level(p->mem_ctx,
7619                                           get_session_info_system(),
7620                                           p->msg_ctx,
7621                                           cservername,
7622                                           r->in.environment,
7623                                           r->in.level,
7624                                           r->out.info,
7625                                           r->out.count);
7626         if (!W_ERROR_IS_OK(result)) {
7627                 return result;
7628         }
7629
7630         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7631                                                      spoolss_EnumPrinterDrivers,
7632                                                      *r->out.info, r->in.level,
7633                                                      *r->out.count);
7634         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7635         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7636
7637         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7638 }
7639
7640 /****************************************************************
7641  _spoolss_EnumForms
7642 ****************************************************************/
7643
7644 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7645                           struct spoolss_EnumForms *r)
7646 {
7647         WERROR result;
7648
7649         *r->out.count = 0;
7650         *r->out.needed = 0;
7651         *r->out.info = NULL;
7652
7653         /* that's an [in out] buffer */
7654
7655         if (!r->in.buffer && (r->in.offered != 0) ) {
7656                 return WERR_INVALID_PARAM;
7657         }
7658
7659         DEBUG(4,("_spoolss_EnumForms\n"));
7660         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7661         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7662
7663         switch (r->in.level) {
7664         case 1:
7665                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7666                                                    get_session_info_system(),
7667                                                    p->msg_ctx,
7668                                                    r->out.count,
7669                                                    r->out.info);
7670                 break;
7671         default:
7672                 result = WERR_UNKNOWN_LEVEL;
7673                 break;
7674         }
7675
7676         if (!W_ERROR_IS_OK(result)) {
7677                 return result;
7678         }
7679
7680         if (*r->out.count == 0) {
7681                 return WERR_NO_MORE_ITEMS;
7682         }
7683
7684         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7685                                                      spoolss_EnumForms,
7686                                                      *r->out.info, r->in.level,
7687                                                      *r->out.count);
7688         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7689         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7690
7691         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7692 }
7693
7694 /****************************************************************
7695  _spoolss_GetForm
7696 ****************************************************************/
7697
7698 WERROR _spoolss_GetForm(struct pipes_struct *p,
7699                         struct spoolss_GetForm *r)
7700 {
7701         WERROR result;
7702
7703         /* that's an [in out] buffer */
7704
7705         if (!r->in.buffer && (r->in.offered != 0)) {
7706                 return WERR_INVALID_PARAM;
7707         }
7708
7709         DEBUG(4,("_spoolss_GetForm\n"));
7710         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7711         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7712
7713         switch (r->in.level) {
7714         case 1:
7715                 result = winreg_printer_getform1_internal(p->mem_ctx,
7716                                                  get_session_info_system(),
7717                                                  p->msg_ctx,
7718                                                  r->in.form_name,
7719                                                  &r->out.info->info1);
7720                 break;
7721         default:
7722                 result = WERR_UNKNOWN_LEVEL;
7723                 break;
7724         }
7725
7726         if (!W_ERROR_IS_OK(result)) {
7727                 TALLOC_FREE(r->out.info);
7728                 return result;
7729         }
7730
7731         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7732                                                r->out.info, r->in.level);
7733         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7734
7735         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7736 }
7737
7738 /****************************************************************************
7739 ****************************************************************************/
7740
7741 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7742                           struct spoolss_PortInfo1 *r,
7743                           const char *name)
7744 {
7745         r->port_name = talloc_strdup(mem_ctx, name);
7746         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7747
7748         return WERR_OK;
7749 }
7750
7751 /****************************************************************************
7752  TODO: This probably needs distinguish between TCP/IP and Local ports
7753  somehow.
7754 ****************************************************************************/
7755
7756 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7757                           struct spoolss_PortInfo2 *r,
7758                           const char *name)
7759 {
7760         r->port_name = talloc_strdup(mem_ctx, name);
7761         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7762
7763         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7764         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7765
7766         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7767         W_ERROR_HAVE_NO_MEMORY(r->description);
7768
7769         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7770         r->reserved = 0;
7771
7772         return WERR_OK;
7773 }
7774
7775
7776 /****************************************************************************
7777  wrapper around the enumer ports command
7778 ****************************************************************************/
7779
7780 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7781 {
7782         char *cmd = lp_enumports_cmd();
7783         char **qlines = NULL;
7784         char *command = NULL;
7785         int numlines;
7786         int ret;
7787         int fd;
7788
7789         *count = 0;
7790         *lines = NULL;
7791
7792         /* if no hook then just fill in the default port */
7793
7794         if ( !*cmd ) {
7795                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7796                         return WERR_NOMEM;
7797                 }
7798                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7799                         TALLOC_FREE(qlines);
7800                         return WERR_NOMEM;
7801                 }
7802                 qlines[1] = NULL;
7803                 numlines = 1;
7804         }
7805         else {
7806                 /* we have a valid enumport command */
7807
7808                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7809                 if (!command) {
7810                         return WERR_NOMEM;
7811                 }
7812
7813                 DEBUG(10,("Running [%s]\n", command));
7814                 ret = smbrun(command, &fd);
7815                 DEBUG(10,("Returned [%d]\n", ret));
7816                 TALLOC_FREE(command);
7817                 if (ret != 0) {
7818                         if (fd != -1) {
7819                                 close(fd);
7820                         }
7821                         return WERR_ACCESS_DENIED;
7822                 }
7823
7824                 numlines = 0;
7825                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7826                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7827                 close(fd);
7828         }
7829
7830         *count = numlines;
7831         *lines = qlines;
7832
7833         return WERR_OK;
7834 }
7835
7836 /****************************************************************************
7837  enumports level 1.
7838 ****************************************************************************/
7839
7840 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7841                                 union spoolss_PortInfo **info_p,
7842                                 uint32_t *count)
7843 {
7844         union spoolss_PortInfo *info = NULL;
7845         int i=0;
7846         WERROR result = WERR_OK;
7847         char **qlines = NULL;
7848         int numlines = 0;
7849
7850         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7851         if (!W_ERROR_IS_OK(result)) {
7852                 goto out;
7853         }
7854
7855         if (numlines) {
7856                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7857                 if (!info) {
7858                         DEBUG(10,("Returning WERR_NOMEM\n"));
7859                         result = WERR_NOMEM;
7860                         goto out;
7861                 }
7862
7863                 for (i=0; i<numlines; i++) {
7864                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7865                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7866                         if (!W_ERROR_IS_OK(result)) {
7867                                 goto out;
7868                         }
7869                 }
7870         }
7871         TALLOC_FREE(qlines);
7872
7873 out:
7874         if (!W_ERROR_IS_OK(result)) {
7875                 TALLOC_FREE(info);
7876                 TALLOC_FREE(qlines);
7877                 *count = 0;
7878                 *info_p = NULL;
7879                 return result;
7880         }
7881
7882         *info_p = info;
7883         *count = numlines;
7884
7885         return WERR_OK;
7886 }
7887
7888 /****************************************************************************
7889  enumports level 2.
7890 ****************************************************************************/
7891
7892 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7893                                 union spoolss_PortInfo **info_p,
7894                                 uint32_t *count)
7895 {
7896         union spoolss_PortInfo *info = NULL;
7897         int i=0;
7898         WERROR result = WERR_OK;
7899         char **qlines = NULL;
7900         int numlines = 0;
7901
7902         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7903         if (!W_ERROR_IS_OK(result)) {
7904                 goto out;
7905         }
7906
7907         if (numlines) {
7908                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7909                 if (!info) {
7910                         DEBUG(10,("Returning WERR_NOMEM\n"));
7911                         result = WERR_NOMEM;
7912                         goto out;
7913                 }
7914
7915                 for (i=0; i<numlines; i++) {
7916                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7917                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7918                         if (!W_ERROR_IS_OK(result)) {
7919                                 goto out;
7920                         }
7921                 }
7922         }
7923         TALLOC_FREE(qlines);
7924
7925 out:
7926         if (!W_ERROR_IS_OK(result)) {
7927                 TALLOC_FREE(info);
7928                 TALLOC_FREE(qlines);
7929                 *count = 0;
7930                 *info_p = NULL;
7931                 return result;
7932         }
7933
7934         *info_p = info;
7935         *count = numlines;
7936
7937         return WERR_OK;
7938 }
7939
7940 /****************************************************************
7941  _spoolss_EnumPorts
7942 ****************************************************************/
7943
7944 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7945                           struct spoolss_EnumPorts *r)
7946 {
7947         WERROR result;
7948
7949         /* that's an [in out] buffer */
7950
7951         if (!r->in.buffer && (r->in.offered != 0)) {
7952                 return WERR_INVALID_PARAM;
7953         }
7954
7955         DEBUG(4,("_spoolss_EnumPorts\n"));
7956
7957         *r->out.count = 0;
7958         *r->out.needed = 0;
7959         *r->out.info = NULL;
7960
7961         switch (r->in.level) {
7962         case 1:
7963                 result = enumports_level_1(p->mem_ctx, r->out.info,
7964                                            r->out.count);
7965                 break;
7966         case 2:
7967                 result = enumports_level_2(p->mem_ctx, r->out.info,
7968                                            r->out.count);
7969                 break;
7970         default:
7971                 return WERR_UNKNOWN_LEVEL;
7972         }
7973
7974         if (!W_ERROR_IS_OK(result)) {
7975                 return result;
7976         }
7977
7978         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7979                                                      spoolss_EnumPorts,
7980                                                      *r->out.info, r->in.level,
7981                                                      *r->out.count);
7982         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7983         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7984
7985         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7986 }
7987
7988 /****************************************************************************
7989 ****************************************************************************/
7990
7991 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7992                                            const char *server,
7993                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
7994                                            struct spoolss_DeviceMode *devmode,
7995                                            struct security_descriptor *secdesc,
7996                                            struct spoolss_UserLevelCtr *user_ctr,
7997                                            struct policy_handle *handle)
7998 {
7999         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8000         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8001         int     snum;
8002         WERROR err = WERR_OK;
8003
8004         /* samba does not have a concept of local, non-shared printers yet, so
8005          * make sure we always setup sharename - gd */
8006         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8007             (info2->printername != NULL && info2->printername[0] != '\0')) {
8008                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8009                         "no sharename has been set, setting printername %s as sharename\n",
8010                         info2->printername));
8011                 info2->sharename = info2->printername;
8012         }
8013
8014         /* check to see if the printer already exists */
8015         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8016                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8017                         info2->sharename));
8018                 return WERR_PRINTER_ALREADY_EXISTS;
8019         }
8020
8021         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8022                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8023                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8024                                 info2->printername));
8025                         return WERR_PRINTER_ALREADY_EXISTS;
8026                 }
8027         }
8028
8029         /* validate printer info struct */
8030         if (!info2->printername || strlen(info2->printername) == 0) {
8031                 return WERR_INVALID_PRINTER_NAME;
8032         }
8033         if (!info2->portname || strlen(info2->portname) == 0) {
8034                 return WERR_UNKNOWN_PORT;
8035         }
8036         if (!info2->drivername || strlen(info2->drivername) == 0) {
8037                 return WERR_UNKNOWN_PRINTER_DRIVER;
8038         }
8039         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8040                 return WERR_UNKNOWN_PRINTPROCESSOR;
8041         }
8042
8043         /* FIXME!!!  smbd should check to see if the driver is installed before
8044            trying to add a printer like this  --jerry */
8045
8046         if (*lp_addprinter_cmd() ) {
8047                 char *raddr;
8048
8049                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8050                                                          p->mem_ctx);
8051                 if (raddr == NULL) {
8052                         return WERR_NOMEM;
8053                 }
8054
8055                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8056                                        info2, raddr,
8057                                        p->msg_ctx) ) {
8058                         return WERR_ACCESS_DENIED;
8059                 }
8060         } else {
8061                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8062                         "smb.conf parameter \"addprinter command\" is defined. This "
8063                         "parameter must exist for this call to succeed\n",
8064                         info2->sharename ));
8065         }
8066
8067         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8068                 return WERR_ACCESS_DENIED;
8069         }
8070
8071         /* you must be a printer admin to add a new printer */
8072         if (!print_access_check(p->session_info,
8073                                 p->msg_ctx,
8074                                 snum,
8075                                 PRINTER_ACCESS_ADMINISTER)) {
8076                 return WERR_ACCESS_DENIED;
8077         }
8078
8079         /*
8080          * Do sanity check on the requested changes for Samba.
8081          */
8082
8083         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8084                 return WERR_INVALID_PARAM;
8085         }
8086
8087         if (devmode == NULL) {
8088                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8089         }
8090
8091         err = update_dsspooler(p->mem_ctx,
8092                                get_session_info_system(),
8093                                p->msg_ctx,
8094                                0,
8095                                info2,
8096                                NULL);
8097         if (!W_ERROR_IS_OK(err)) {
8098                 return err;
8099         }
8100
8101         err = winreg_update_printer_internal(p->mem_ctx,
8102                                     get_session_info_system(),
8103                                     p->msg_ctx,
8104                                     info2->sharename,
8105                                     info2_mask,
8106                                     info2,
8107                                     devmode,
8108                                     secdesc);
8109         if (!W_ERROR_IS_OK(err)) {
8110                 return err;
8111         }
8112
8113         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8114         if (!W_ERROR_IS_OK(err)) {
8115                 /* Handle open failed - remove addition. */
8116                 ZERO_STRUCTP(handle);
8117                 return err;
8118         }
8119
8120         return WERR_OK;
8121 }
8122
8123 /****************************************************************
8124  _spoolss_AddPrinterEx
8125 ****************************************************************/
8126
8127 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8128                              struct spoolss_AddPrinterEx *r)
8129 {
8130         switch (r->in.info_ctr->level) {
8131         case 1:
8132                 /* we don't handle yet */
8133                 /* but I know what to do ... */
8134                 return WERR_UNKNOWN_LEVEL;
8135         case 2:
8136                 return spoolss_addprinterex_level_2(p, r->in.server,
8137                                                     r->in.info_ctr,
8138                                                     r->in.devmode_ctr->devmode,
8139                                                     r->in.secdesc_ctr->sd,
8140                                                     r->in.userlevel_ctr,
8141                                                     r->out.handle);
8142         default:
8143                 return WERR_UNKNOWN_LEVEL;
8144         }
8145 }
8146
8147 /****************************************************************
8148  _spoolss_AddPrinter
8149 ****************************************************************/
8150
8151 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8152                            struct spoolss_AddPrinter *r)
8153 {
8154         struct spoolss_AddPrinterEx a;
8155         struct spoolss_UserLevelCtr userlevel_ctr;
8156
8157         ZERO_STRUCT(userlevel_ctr);
8158
8159         userlevel_ctr.level = 1;
8160
8161         a.in.server             = r->in.server;
8162         a.in.info_ctr           = r->in.info_ctr;
8163         a.in.devmode_ctr        = r->in.devmode_ctr;
8164         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8165         a.in.userlevel_ctr      = &userlevel_ctr;
8166         a.out.handle            = r->out.handle;
8167
8168         return _spoolss_AddPrinterEx(p, &a);
8169 }
8170
8171 /****************************************************************
8172  _spoolss_AddPrinterDriverEx
8173 ****************************************************************/
8174
8175 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8176                                    struct spoolss_AddPrinterDriverEx *r)
8177 {
8178         WERROR err = WERR_OK;
8179         const char *driver_name = NULL;
8180         uint32_t version;
8181         const char *fn;
8182
8183         switch (p->opnum) {
8184                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8185                         fn = "_spoolss_AddPrinterDriver";
8186                         break;
8187                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8188                         fn = "_spoolss_AddPrinterDriverEx";
8189                         break;
8190                 default:
8191                         return WERR_INVALID_PARAM;
8192         }
8193
8194         /*
8195          * we only support the semantics of AddPrinterDriver()
8196          * i.e. only copy files that are newer than existing ones
8197          */
8198
8199         if (r->in.flags == 0) {
8200                 return WERR_INVALID_PARAM;
8201         }
8202
8203         if (r->in.flags != APD_COPY_NEW_FILES) {
8204                 return WERR_ACCESS_DENIED;
8205         }
8206
8207         /* FIXME */
8208         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8209                 /* Clever hack from Martin Zielinski <mz@seh.de>
8210                  * to allow downgrade from level 8 (Vista).
8211                  */
8212                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8213                         r->in.info_ctr->level));
8214                 return WERR_UNKNOWN_LEVEL;
8215         }
8216
8217         DEBUG(5,("Cleaning driver's information\n"));
8218         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8219         if (!W_ERROR_IS_OK(err))
8220                 goto done;
8221
8222         DEBUG(5,("Moving driver to final destination\n"));
8223         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8224         if (!W_ERROR_IS_OK(err)) {
8225                 goto done;
8226         }
8227
8228         err = winreg_add_driver_internal(p->mem_ctx,
8229                                 get_session_info_system(),
8230                                 p->msg_ctx,
8231                                 r->in.info_ctr,
8232                                 &driver_name,
8233                                 &version);
8234         if (!W_ERROR_IS_OK(err)) {
8235                 goto done;
8236         }
8237
8238         /*
8239          * I think this is where he DrvUpgradePrinter() hook would be
8240          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8241          * server.  Right now, we just need to send ourselves a message
8242          * to update each printer bound to this driver.   --jerry
8243          */
8244
8245         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8246                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8247                         fn, driver_name));
8248         }
8249
8250 done:
8251         return err;
8252 }
8253
8254 /****************************************************************
8255  _spoolss_AddPrinterDriver
8256 ****************************************************************/
8257
8258 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8259                                  struct spoolss_AddPrinterDriver *r)
8260 {
8261         struct spoolss_AddPrinterDriverEx a;
8262
8263         switch (r->in.info_ctr->level) {
8264         case 2:
8265         case 3:
8266         case 4:
8267         case 5:
8268                 break;
8269         default:
8270                 return WERR_UNKNOWN_LEVEL;
8271         }
8272
8273         a.in.servername         = r->in.servername;
8274         a.in.info_ctr           = r->in.info_ctr;
8275         a.in.flags              = APD_COPY_NEW_FILES;
8276
8277         return _spoolss_AddPrinterDriverEx(p, &a);
8278 }
8279
8280 /****************************************************************************
8281 ****************************************************************************/
8282
8283 struct _spoolss_paths {
8284         int type;
8285         const char *share;
8286         const char *dir;
8287 };
8288
8289 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8290
8291 static const struct _spoolss_paths spoolss_paths[]= {
8292         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8293         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8294 };
8295
8296 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8297                                           const char *servername,
8298                                           const char *environment,
8299                                           int component,
8300                                           char **path)
8301 {
8302         const char *pservername = NULL;
8303         const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8304         const char *short_archi;
8305
8306         *path = NULL;
8307
8308         /* environment may be empty */
8309         if (environment && strlen(environment)) {
8310                 long_archi = environment;
8311         }
8312
8313         /* servername may be empty */
8314         if (servername && strlen(servername)) {
8315                 pservername = canon_servername(servername);
8316
8317                 if (!is_myname_or_ipaddr(pservername)) {
8318                         return WERR_INVALID_PARAM;
8319                 }
8320         }
8321
8322         if (!(short_archi = get_short_archi(long_archi))) {
8323                 return WERR_INVALID_ENVIRONMENT;
8324         }
8325
8326         switch (component) {
8327         case SPOOLSS_PRTPROCS_PATH:
8328         case SPOOLSS_DRIVER_PATH:
8329                 if (pservername) {
8330                         *path = talloc_asprintf(mem_ctx,
8331                                         "\\\\%s\\%s\\%s",
8332                                         pservername,
8333                                         spoolss_paths[component].share,
8334                                         short_archi);
8335                 } else {
8336                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8337                                         SPOOLSS_DEFAULT_SERVER_PATH,
8338                                         spoolss_paths[component].dir,
8339                                         short_archi);
8340                 }
8341                 break;
8342         default:
8343                 return WERR_INVALID_PARAM;
8344         }
8345
8346         if (!*path) {
8347                 return WERR_NOMEM;
8348         }
8349
8350         return WERR_OK;
8351 }
8352
8353 /****************************************************************************
8354 ****************************************************************************/
8355
8356 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8357                                           const char *servername,
8358                                           const char *environment,
8359                                           struct spoolss_DriverDirectoryInfo1 *r)
8360 {
8361         WERROR werr;
8362         char *path = NULL;
8363
8364         werr = compose_spoolss_server_path(mem_ctx,
8365                                            servername,
8366                                            environment,
8367                                            SPOOLSS_DRIVER_PATH,
8368                                            &path);
8369         if (!W_ERROR_IS_OK(werr)) {
8370                 return werr;
8371         }
8372
8373         DEBUG(4,("printer driver directory: [%s]\n", path));
8374
8375         r->directory_name = path;
8376
8377         return WERR_OK;
8378 }
8379
8380 /****************************************************************
8381  _spoolss_GetPrinterDriverDirectory
8382 ****************************************************************/
8383
8384 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8385                                           struct spoolss_GetPrinterDriverDirectory *r)
8386 {
8387         WERROR werror;
8388
8389         /* that's an [in out] buffer */
8390
8391         if (!r->in.buffer && (r->in.offered != 0)) {
8392                 return WERR_INVALID_PARAM;
8393         }
8394
8395         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8396                 r->in.level));
8397
8398         *r->out.needed = 0;
8399
8400         /* r->in.level is ignored */
8401
8402         werror = getprinterdriverdir_level_1(p->mem_ctx,
8403                                              r->in.server,
8404                                              r->in.environment,
8405                                              &r->out.info->info1);
8406         if (!W_ERROR_IS_OK(werror)) {
8407                 TALLOC_FREE(r->out.info);
8408                 return werror;
8409         }
8410
8411         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8412                                                r->out.info, r->in.level);
8413         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8414
8415         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8416 }
8417
8418 /****************************************************************
8419  _spoolss_EnumPrinterData
8420 ****************************************************************/
8421
8422 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8423                                 struct spoolss_EnumPrinterData *r)
8424 {
8425         WERROR result;
8426         struct spoolss_EnumPrinterDataEx r2;
8427         uint32_t count;
8428         struct spoolss_PrinterEnumValues *info, *val = NULL;
8429         uint32_t needed;
8430
8431         r2.in.handle    = r->in.handle;
8432         r2.in.key_name  = "PrinterDriverData";
8433         r2.in.offered   = 0;
8434         r2.out.count    = &count;
8435         r2.out.info     = &info;
8436         r2.out.needed   = &needed;
8437
8438         result = _spoolss_EnumPrinterDataEx(p, &r2);
8439         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8440                 r2.in.offered = needed;
8441                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8442         }
8443         if (!W_ERROR_IS_OK(result)) {
8444                 return result;
8445         }
8446
8447         /*
8448          * The NT machine wants to know the biggest size of value and data
8449          *
8450          * cf: MSDN EnumPrinterData remark section
8451          */
8452
8453         if (!r->in.value_offered && !r->in.data_offered) {
8454                 uint32_t biggest_valuesize = 0;
8455                 uint32_t biggest_datasize = 0;
8456                 int i, name_length;
8457
8458                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8459
8460                 for (i=0; i<count; i++) {
8461
8462                         name_length = strlen(info[i].value_name);
8463                         if (strlen(info[i].value_name) > biggest_valuesize) {
8464                                 biggest_valuesize = name_length;
8465                         }
8466
8467                         if (info[i].data_length > biggest_datasize) {
8468                                 biggest_datasize = info[i].data_length;
8469                         }
8470
8471                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8472                                 biggest_datasize));
8473                 }
8474
8475                 /* the value is an UNICODE string but real_value_size is the length
8476                    in bytes including the trailing 0 */
8477
8478                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8479                 *r->out.data_needed  = biggest_datasize;
8480
8481                 DEBUG(6,("final values: [%d], [%d]\n",
8482                         *r->out.value_needed, *r->out.data_needed));
8483
8484                 return WERR_OK;
8485         }
8486
8487         if (r->in.enum_index < count) {
8488                 val = &info[r->in.enum_index];
8489         }
8490
8491         if (val == NULL) {
8492                 /* out_value should default to "" or else NT4 has
8493                    problems unmarshalling the response */
8494
8495                 if (r->in.value_offered) {
8496                         *r->out.value_needed = 1;
8497                         r->out.value_name = talloc_strdup(r, "");
8498                         if (!r->out.value_name) {
8499                                 return WERR_NOMEM;
8500                         }
8501                 } else {
8502                         r->out.value_name = NULL;
8503                         *r->out.value_needed = 0;
8504                 }
8505
8506                 /* the data is counted in bytes */
8507
8508                 *r->out.data_needed = r->in.data_offered;
8509
8510                 result = WERR_NO_MORE_ITEMS;
8511         } else {
8512                 /*
8513                  * the value is:
8514                  * - counted in bytes in the request
8515                  * - counted in UNICODE chars in the max reply
8516                  * - counted in bytes in the real size
8517                  *
8518                  * take a pause *before* coding not *during* coding
8519                  */
8520
8521                 /* name */
8522                 if (r->in.value_offered) {
8523                         r->out.value_name = talloc_strdup(r, val->value_name);
8524                         if (!r->out.value_name) {
8525                                 return WERR_NOMEM;
8526                         }
8527                         *r->out.value_needed = val->value_name_len;
8528                 } else {
8529                         r->out.value_name = NULL;
8530                         *r->out.value_needed = 0;
8531                 }
8532
8533                 /* type */
8534
8535                 *r->out.type = val->type;
8536
8537                 /* data - counted in bytes */
8538
8539                 /*
8540                  * See the section "Dynamically Typed Query Parameters"
8541                  * in MS-RPRN.
8542                  */
8543
8544                 if (r->out.data && val->data && val->data->data &&
8545                                 val->data_length && r->in.data_offered) {
8546                         memcpy(r->out.data, val->data->data,
8547                                 MIN(val->data_length,r->in.data_offered));
8548                 }
8549
8550                 *r->out.data_needed = val->data_length;
8551
8552                 result = WERR_OK;
8553         }
8554
8555         return result;
8556 }
8557
8558 /****************************************************************
8559  _spoolss_SetPrinterData
8560 ****************************************************************/
8561
8562 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8563                                struct spoolss_SetPrinterData *r)
8564 {
8565         struct spoolss_SetPrinterDataEx r2;
8566
8567         r2.in.handle            = r->in.handle;
8568         r2.in.key_name          = "PrinterDriverData";
8569         r2.in.value_name        = r->in.value_name;
8570         r2.in.type              = r->in.type;
8571         r2.in.data              = r->in.data;
8572         r2.in.offered           = r->in.offered;
8573
8574         return _spoolss_SetPrinterDataEx(p, &r2);
8575 }
8576
8577 /****************************************************************
8578  _spoolss_ResetPrinter
8579 ****************************************************************/
8580
8581 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8582                              struct spoolss_ResetPrinter *r)
8583 {
8584         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8585         int             snum;
8586
8587         DEBUG(5,("_spoolss_ResetPrinter\n"));
8588
8589         /*
8590          * All we do is to check to see if the handle and queue is valid.
8591          * This call really doesn't mean anything to us because we only
8592          * support RAW printing.   --jerry
8593          */
8594
8595         if (!Printer) {
8596                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8597                         OUR_HANDLE(r->in.handle)));
8598                 return WERR_BADFID;
8599         }
8600
8601         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8602                 return WERR_BADFID;
8603
8604
8605         /* blindly return success */
8606         return WERR_OK;
8607 }
8608
8609 /****************************************************************
8610  _spoolss_DeletePrinterData
8611 ****************************************************************/
8612
8613 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8614                                   struct spoolss_DeletePrinterData *r)
8615 {
8616         struct spoolss_DeletePrinterDataEx r2;
8617
8618         r2.in.handle            = r->in.handle;
8619         r2.in.key_name          = "PrinterDriverData";
8620         r2.in.value_name        = r->in.value_name;
8621
8622         return _spoolss_DeletePrinterDataEx(p, &r2);
8623 }
8624
8625 /****************************************************************
8626  _spoolss_AddForm
8627 ****************************************************************/
8628
8629 WERROR _spoolss_AddForm(struct pipes_struct *p,
8630                         struct spoolss_AddForm *r)
8631 {
8632         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8633         int snum = -1;
8634         WERROR status = WERR_OK;
8635         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8636         struct dcerpc_binding_handle *b;
8637         TALLOC_CTX *tmp_ctx = NULL;
8638
8639         DEBUG(5,("_spoolss_AddForm\n"));
8640
8641         if (!Printer) {
8642                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8643                         OUR_HANDLE(r->in.handle)));
8644                 return WERR_BADFID;
8645         }
8646
8647         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8648            and not a printer admin, then fail */
8649
8650         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8651             !security_token_has_privilege(p->session_info->security_token,
8652                                           SEC_PRIV_PRINT_OPERATOR)) {
8653                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8654                 return WERR_ACCESS_DENIED;
8655         }
8656
8657         switch (form->flags) {
8658         case SPOOLSS_FORM_USER:
8659         case SPOOLSS_FORM_BUILTIN:
8660         case SPOOLSS_FORM_PRINTER:
8661                 break;
8662         default:
8663                 return WERR_INVALID_PARAM;
8664         }
8665
8666         tmp_ctx = talloc_new(p->mem_ctx);
8667         if (!tmp_ctx) {
8668                 return WERR_NOMEM;
8669         }
8670
8671         status = winreg_printer_binding_handle(tmp_ctx,
8672                                                get_session_info_system(),
8673                                                p->msg_ctx,
8674                                                &b);
8675         if (!W_ERROR_IS_OK(status)) {
8676                 goto done;
8677         }
8678
8679         status = winreg_printer_addform1(tmp_ctx, b, form);
8680         if (!W_ERROR_IS_OK(status)) {
8681                 goto done;
8682         }
8683
8684         /*
8685          * ChangeID must always be set if this is a printer
8686          */
8687         if (Printer->printer_type == SPLHND_PRINTER) {
8688                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8689                         status = WERR_BADFID;
8690                         goto done;
8691                 }
8692
8693                 status = winreg_printer_update_changeid(tmp_ctx, b,
8694                                                         lp_const_servicename(snum));
8695         }
8696
8697 done:
8698         talloc_free(tmp_ctx);
8699         return status;
8700 }
8701
8702 /****************************************************************
8703  _spoolss_DeleteForm
8704 ****************************************************************/
8705
8706 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8707                            struct spoolss_DeleteForm *r)
8708 {
8709         const char *form_name = r->in.form_name;
8710         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8711         int snum = -1;
8712         WERROR status = WERR_OK;
8713         struct dcerpc_binding_handle *b;
8714         TALLOC_CTX *tmp_ctx = NULL;
8715
8716         DEBUG(5,("_spoolss_DeleteForm\n"));
8717
8718         if (!Printer) {
8719                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8720                         OUR_HANDLE(r->in.handle)));
8721                 return WERR_BADFID;
8722         }
8723
8724         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8725             !security_token_has_privilege(p->session_info->security_token,
8726                                           SEC_PRIV_PRINT_OPERATOR)) {
8727                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8728                 return WERR_ACCESS_DENIED;
8729         }
8730
8731         tmp_ctx = talloc_new(p->mem_ctx);
8732         if (!tmp_ctx) {
8733                 return WERR_NOMEM;
8734         }
8735
8736         status = winreg_printer_binding_handle(tmp_ctx,
8737                                                get_session_info_system(),
8738                                                p->msg_ctx,
8739                                                &b);
8740         if (!W_ERROR_IS_OK(status)) {
8741                 goto done;
8742         }
8743
8744         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8745         if (!W_ERROR_IS_OK(status)) {
8746                 goto done;
8747         }
8748
8749         /*
8750          * ChangeID must always be set if this is a printer
8751          */
8752         if (Printer->printer_type == SPLHND_PRINTER) {
8753                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8754                         status = WERR_BADFID;
8755                         goto done;
8756                 }
8757
8758                 status = winreg_printer_update_changeid(tmp_ctx, b,
8759                                                         lp_const_servicename(snum));
8760         }
8761
8762 done:
8763         talloc_free(tmp_ctx);
8764         return status;
8765 }
8766
8767 /****************************************************************
8768  _spoolss_SetForm
8769 ****************************************************************/
8770
8771 WERROR _spoolss_SetForm(struct pipes_struct *p,
8772                         struct spoolss_SetForm *r)
8773 {
8774         struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8775         const char *form_name = r->in.form_name;
8776         int snum = -1;
8777         WERROR status = WERR_OK;
8778         struct dcerpc_binding_handle *b;
8779         TALLOC_CTX *tmp_ctx = NULL;
8780
8781         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8782
8783         DEBUG(5,("_spoolss_SetForm\n"));
8784
8785         if (!Printer) {
8786                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8787                         OUR_HANDLE(r->in.handle)));
8788                 return WERR_BADFID;
8789         }
8790
8791         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8792            and not a printer admin, then fail */
8793
8794         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8795              !security_token_has_privilege(p->session_info->security_token,
8796                                            SEC_PRIV_PRINT_OPERATOR)) {
8797                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8798                 return WERR_ACCESS_DENIED;
8799         }
8800
8801         tmp_ctx = talloc_new(p->mem_ctx);
8802         if (!tmp_ctx) {
8803                 return WERR_NOMEM;
8804         }
8805
8806         status = winreg_printer_binding_handle(tmp_ctx,
8807                                                get_session_info_system(),
8808                                                p->msg_ctx,
8809                                                &b);
8810         if (!W_ERROR_IS_OK(status)) {
8811                 goto done;
8812         }
8813
8814         status = winreg_printer_setform1(tmp_ctx, b,
8815                                          form_name,
8816                                          form);
8817         if (!W_ERROR_IS_OK(status)) {
8818                 goto done;
8819         }
8820
8821         /*
8822          * ChangeID must always be set if this is a printer
8823          */
8824         if (Printer->printer_type == SPLHND_PRINTER) {
8825                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8826                         status = WERR_BADFID;
8827                         goto done;
8828                 }
8829
8830                 status = winreg_printer_update_changeid(tmp_ctx, b,
8831                                                         lp_const_servicename(snum));
8832         }
8833
8834 done:
8835         talloc_free(tmp_ctx);
8836         return status;
8837 }
8838
8839 /****************************************************************************
8840  fill_print_processor1
8841 ****************************************************************************/
8842
8843 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8844                                     struct spoolss_PrintProcessorInfo1 *r,
8845                                     const char *print_processor_name)
8846 {
8847         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8848         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8849
8850         return WERR_OK;
8851 }
8852
8853 /****************************************************************************
8854  enumprintprocessors level 1.
8855 ****************************************************************************/
8856
8857 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8858                                           union spoolss_PrintProcessorInfo **info_p,
8859                                           uint32_t *count)
8860 {
8861         union spoolss_PrintProcessorInfo *info;
8862         WERROR result;
8863
8864         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8865         W_ERROR_HAVE_NO_MEMORY(info);
8866
8867         *count = 1;
8868
8869         result = fill_print_processor1(info, &info[0].info1, "winprint");
8870         if (!W_ERROR_IS_OK(result)) {
8871                 goto out;
8872         }
8873
8874  out:
8875         if (!W_ERROR_IS_OK(result)) {
8876                 TALLOC_FREE(info);
8877                 *count = 0;
8878                 return result;
8879         }
8880
8881         *info_p = info;
8882
8883         return WERR_OK;
8884 }
8885
8886 /****************************************************************
8887  _spoolss_EnumPrintProcessors
8888 ****************************************************************/
8889
8890 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8891                                     struct spoolss_EnumPrintProcessors *r)
8892 {
8893         WERROR result;
8894
8895         /* that's an [in out] buffer */
8896
8897         if (!r->in.buffer && (r->in.offered != 0)) {
8898                 return WERR_INVALID_PARAM;
8899         }
8900
8901         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8902
8903         /*
8904          * Enumerate the print processors ...
8905          *
8906          * Just reply with "winprint", to keep NT happy
8907          * and I can use my nice printer checker.
8908          */
8909
8910         *r->out.count = 0;
8911         *r->out.needed = 0;
8912         *r->out.info = NULL;
8913
8914         if (!get_short_archi(r->in.environment)) {
8915                 return WERR_INVALID_ENVIRONMENT;
8916         }
8917
8918         switch (r->in.level) {
8919         case 1:
8920                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8921                                                      r->out.count);
8922                 break;
8923         default:
8924                 return WERR_UNKNOWN_LEVEL;
8925         }
8926
8927         if (!W_ERROR_IS_OK(result)) {
8928                 return result;
8929         }
8930
8931         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8932                                                      spoolss_EnumPrintProcessors,
8933                                                      *r->out.info, r->in.level,
8934                                                      *r->out.count);
8935         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8936         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8937
8938         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8939 }
8940
8941 /****************************************************************************
8942  fill_printprocdatatype1
8943 ****************************************************************************/
8944
8945 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8946                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8947                                       const char *name_array)
8948 {
8949         r->name_array = talloc_strdup(mem_ctx, name_array);
8950         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8951
8952         return WERR_OK;
8953 }
8954
8955 /****************************************************************************
8956  enumprintprocdatatypes level 1.
8957 ****************************************************************************/
8958
8959 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8960                                              union spoolss_PrintProcDataTypesInfo **info_p,
8961                                              uint32_t *count)
8962 {
8963         WERROR result;
8964         union spoolss_PrintProcDataTypesInfo *info;
8965
8966         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8967         W_ERROR_HAVE_NO_MEMORY(info);
8968
8969         *count = 1;
8970
8971         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8972         if (!W_ERROR_IS_OK(result)) {
8973                 goto out;
8974         }
8975
8976  out:
8977         if (!W_ERROR_IS_OK(result)) {
8978                 TALLOC_FREE(info);
8979                 *count = 0;
8980                 return result;
8981         }
8982
8983         *info_p = info;
8984
8985         return WERR_OK;
8986 }
8987
8988 /****************************************************************
8989  _spoolss_EnumPrintProcDataTypes
8990 ****************************************************************/
8991
8992 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8993                                        struct spoolss_EnumPrintProcDataTypes *r)
8994 {
8995         WERROR result;
8996
8997         /* that's an [in out] buffer */
8998
8999         if (!r->in.buffer && (r->in.offered != 0)) {
9000                 return WERR_INVALID_PARAM;
9001         }
9002
9003         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9004
9005         *r->out.count = 0;
9006         *r->out.needed = 0;
9007         *r->out.info = NULL;
9008
9009         if (r->in.print_processor_name == NULL ||
9010             !strequal(r->in.print_processor_name, "winprint")) {
9011                 return WERR_UNKNOWN_PRINTPROCESSOR;
9012         }
9013
9014         switch (r->in.level) {
9015         case 1:
9016                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9017                                                         r->out.count);
9018                 break;
9019         default:
9020                 return WERR_UNKNOWN_LEVEL;
9021         }
9022
9023         if (!W_ERROR_IS_OK(result)) {
9024                 return result;
9025         }
9026
9027         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9028                                                      spoolss_EnumPrintProcDataTypes,
9029                                                      *r->out.info, r->in.level,
9030                                                      *r->out.count);
9031         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9032         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9033
9034         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9035 }
9036
9037 /****************************************************************************
9038  fill_monitor_1
9039 ****************************************************************************/
9040
9041 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9042                              struct spoolss_MonitorInfo1 *r,
9043                              const char *monitor_name)
9044 {
9045         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9046         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9047
9048         return WERR_OK;
9049 }
9050
9051 /****************************************************************************
9052  fill_monitor_2
9053 ****************************************************************************/
9054
9055 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9056                              struct spoolss_MonitorInfo2 *r,
9057                              const char *monitor_name,
9058                              const char *environment,
9059                              const char *dll_name)
9060 {
9061         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9062         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9063         r->environment                  = talloc_strdup(mem_ctx, environment);
9064         W_ERROR_HAVE_NO_MEMORY(r->environment);
9065         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9066         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9067
9068         return WERR_OK;
9069 }
9070
9071 /****************************************************************************
9072  enumprintmonitors level 1.
9073 ****************************************************************************/
9074
9075 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9076                                         union spoolss_MonitorInfo **info_p,
9077                                         uint32_t *count)
9078 {
9079         union spoolss_MonitorInfo *info;
9080         WERROR result = WERR_OK;
9081
9082         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9083         W_ERROR_HAVE_NO_MEMORY(info);
9084
9085         *count = 2;
9086
9087         result = fill_monitor_1(info, &info[0].info1,
9088                                 SPL_LOCAL_PORT);
9089         if (!W_ERROR_IS_OK(result)) {
9090                 goto out;
9091         }
9092
9093         result = fill_monitor_1(info, &info[1].info1,
9094                                 SPL_TCPIP_PORT);
9095         if (!W_ERROR_IS_OK(result)) {
9096                 goto out;
9097         }
9098
9099 out:
9100         if (!W_ERROR_IS_OK(result)) {
9101                 TALLOC_FREE(info);
9102                 *count = 0;
9103                 return result;
9104         }
9105
9106         *info_p = info;
9107
9108         return WERR_OK;
9109 }
9110
9111 /****************************************************************************
9112  enumprintmonitors level 2.
9113 ****************************************************************************/
9114
9115 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9116                                         union spoolss_MonitorInfo **info_p,
9117                                         uint32_t *count)
9118 {
9119         union spoolss_MonitorInfo *info;
9120         WERROR result = WERR_OK;
9121
9122         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9123         W_ERROR_HAVE_NO_MEMORY(info);
9124
9125         *count = 2;
9126
9127         result = fill_monitor_2(info, &info[0].info2,
9128                                 SPL_LOCAL_PORT,
9129                                 "Windows NT X86", /* FIXME */
9130                                 "localmon.dll");
9131         if (!W_ERROR_IS_OK(result)) {
9132                 goto out;
9133         }
9134
9135         result = fill_monitor_2(info, &info[1].info2,
9136                                 SPL_TCPIP_PORT,
9137                                 "Windows NT X86", /* FIXME */
9138                                 "tcpmon.dll");
9139         if (!W_ERROR_IS_OK(result)) {
9140                 goto out;
9141         }
9142
9143 out:
9144         if (!W_ERROR_IS_OK(result)) {
9145                 TALLOC_FREE(info);
9146                 *count = 0;
9147                 return result;
9148         }
9149
9150         *info_p = info;
9151
9152         return WERR_OK;
9153 }
9154
9155 /****************************************************************
9156  _spoolss_EnumMonitors
9157 ****************************************************************/
9158
9159 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9160                              struct spoolss_EnumMonitors *r)
9161 {
9162         WERROR result;
9163
9164         /* that's an [in out] buffer */
9165
9166         if (!r->in.buffer && (r->in.offered != 0)) {
9167                 return WERR_INVALID_PARAM;
9168         }
9169
9170         DEBUG(5,("_spoolss_EnumMonitors\n"));
9171
9172         /*
9173          * Enumerate the print monitors ...
9174          *
9175          * Just reply with "Local Port", to keep NT happy
9176          * and I can use my nice printer checker.
9177          */
9178
9179         *r->out.count = 0;
9180         *r->out.needed = 0;
9181         *r->out.info = NULL;
9182
9183         switch (r->in.level) {
9184         case 1:
9185                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9186                                                    r->out.count);
9187                 break;
9188         case 2:
9189                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9190                                                    r->out.count);
9191                 break;
9192         default:
9193                 return WERR_UNKNOWN_LEVEL;
9194         }
9195
9196         if (!W_ERROR_IS_OK(result)) {
9197                 return result;
9198         }
9199
9200         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9201                                                      spoolss_EnumMonitors,
9202                                                      *r->out.info, r->in.level,
9203                                                      *r->out.count);
9204         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9205         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9206
9207         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9208 }
9209
9210 /****************************************************************************
9211 ****************************************************************************/
9212
9213 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9214                              const print_queue_struct *queue,
9215                              int count, int snum,
9216                              struct spoolss_PrinterInfo2 *pinfo2,
9217                              uint32_t jobid,
9218                              struct spoolss_JobInfo1 *r)
9219 {
9220         int i = 0;
9221         bool found = false;
9222
9223         for (i=0; i<count; i++) {
9224                 if (queue[i].sysjob == (int)jobid) {
9225                         found = true;
9226                         break;
9227                 }
9228         }
9229
9230         if (found == false) {
9231                 /* NT treats not found as bad param... yet another bad choice */
9232                 return WERR_INVALID_PARAM;
9233         }
9234
9235         return fill_job_info1(mem_ctx,
9236                               r,
9237                               &queue[i],
9238                               i,
9239                               snum,
9240                               pinfo2);
9241 }
9242
9243 /****************************************************************************
9244 ****************************************************************************/
9245
9246 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9247                              const print_queue_struct *queue,
9248                              int count, int snum,
9249                              struct spoolss_PrinterInfo2 *pinfo2,
9250                              uint32_t jobid,
9251                              struct spoolss_JobInfo2 *r)
9252 {
9253         int i = 0;
9254         bool found = false;
9255         struct spoolss_DeviceMode *devmode;
9256         WERROR result;
9257
9258         for (i=0; i<count; i++) {
9259                 if (queue[i].sysjob == (int)jobid) {
9260                         found = true;
9261                         break;
9262                 }
9263         }
9264
9265         if (found == false) {
9266                 /* NT treats not found as bad param... yet another bad
9267                    choice */
9268                 return WERR_INVALID_PARAM;
9269         }
9270
9271         /*
9272          * if the print job does not have a DEVMODE associated with it,
9273          * just use the one for the printer. A NULL devicemode is not
9274          *  a failure condition
9275          */
9276
9277         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9278         if (!devmode) {
9279                 result = spoolss_create_default_devmode(mem_ctx,
9280                                                 pinfo2->printername,
9281                                                 &devmode);
9282                 if (!W_ERROR_IS_OK(result)) {
9283                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9284                         return result;
9285                 }
9286         }
9287
9288         return fill_job_info2(mem_ctx,
9289                               r,
9290                               &queue[i],
9291                               i,
9292                               snum,
9293                               pinfo2,
9294                               devmode);
9295 }
9296
9297 /****************************************************************
9298  _spoolss_GetJob
9299 ****************************************************************/
9300
9301 WERROR _spoolss_GetJob(struct pipes_struct *p,
9302                        struct spoolss_GetJob *r)
9303 {
9304         WERROR result = WERR_OK;
9305         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9306         int snum;
9307         int count;
9308         print_queue_struct      *queue = NULL;
9309         print_status_struct prt_status;
9310
9311         /* that's an [in out] buffer */
9312
9313         if (!r->in.buffer && (r->in.offered != 0)) {
9314                 return WERR_INVALID_PARAM;
9315         }
9316
9317         DEBUG(5,("_spoolss_GetJob\n"));
9318
9319         *r->out.needed = 0;
9320
9321         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9322                 return WERR_BADFID;
9323         }
9324
9325         result = winreg_get_printer_internal(p->mem_ctx,
9326                                     get_session_info_system(),
9327                                     p->msg_ctx,
9328                                     lp_const_servicename(snum),
9329                                     &pinfo2);
9330         if (!W_ERROR_IS_OK(result)) {
9331                 return result;
9332         }
9333
9334         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9335
9336         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9337                      count, prt_status.status, prt_status.message));
9338
9339         switch (r->in.level) {
9340         case 1:
9341                 result = getjob_level_1(p->mem_ctx,
9342                                         queue, count, snum, pinfo2,
9343                                         r->in.job_id, &r->out.info->info1);
9344                 break;
9345         case 2:
9346                 result = getjob_level_2(p->mem_ctx,
9347                                         queue, count, snum, pinfo2,
9348                                         r->in.job_id, &r->out.info->info2);
9349                 break;
9350         default:
9351                 result = WERR_UNKNOWN_LEVEL;
9352                 break;
9353         }
9354
9355         SAFE_FREE(queue);
9356         TALLOC_FREE(pinfo2);
9357
9358         if (!W_ERROR_IS_OK(result)) {
9359                 TALLOC_FREE(r->out.info);
9360                 return result;
9361         }
9362
9363         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9364                                                                                    r->in.level);
9365         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9366
9367         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9368 }
9369
9370 /****************************************************************
9371  _spoolss_GetPrinterDataEx
9372 ****************************************************************/
9373
9374 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9375                                  struct spoolss_GetPrinterDataEx *r)
9376 {
9377
9378         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9379         const char *printer;
9380         int                     snum = 0;
9381         WERROR result = WERR_OK;
9382         DATA_BLOB blob;
9383         enum winreg_Type val_type = REG_NONE;
9384         uint8_t *val_data = NULL;
9385         uint32_t val_size = 0;
9386         struct dcerpc_binding_handle *b;
9387         TALLOC_CTX *tmp_ctx;
9388
9389         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9390
9391         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9392                 r->in.key_name, r->in.value_name));
9393
9394         /* in case of problem, return some default values */
9395
9396         *r->out.needed  = 0;
9397         *r->out.type    = REG_NONE;
9398
9399         tmp_ctx = talloc_new(p->mem_ctx);
9400         if (!tmp_ctx) {
9401                 return WERR_NOMEM;
9402         }
9403
9404         if (!Printer) {
9405                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9406                         OUR_HANDLE(r->in.handle)));
9407                 result = WERR_BADFID;
9408                 goto done;
9409         }
9410
9411         /* check to see if the keyname is valid */
9412         if (!strlen(r->in.key_name)) {
9413                 result = WERR_INVALID_PARAM;
9414                 goto done;
9415         }
9416
9417         /* Is the handle to a printer or to the server? */
9418
9419         if (Printer->printer_type == SPLHND_SERVER) {
9420
9421                 union spoolss_PrinterData data;
9422
9423                 result = getprinterdata_printer_server(tmp_ctx,
9424                                                        r->in.value_name,
9425                                                        r->out.type,
9426                                                        &data);
9427                 if (!W_ERROR_IS_OK(result)) {
9428                         goto done;
9429                 }
9430
9431                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9432                                                   *r->out.type, &data);
9433                 if (!W_ERROR_IS_OK(result)) {
9434                         goto done;
9435                 }
9436
9437                 *r->out.needed = blob.length;
9438
9439                 if (r->in.offered >= *r->out.needed) {
9440                         memcpy(r->out.data, blob.data, blob.length);
9441                 }
9442
9443                 result = WERR_OK;
9444                 goto done;
9445         }
9446
9447         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9448                 result = WERR_BADFID;
9449                 goto done;
9450         }
9451         printer = lp_const_servicename(snum);
9452
9453         result = winreg_printer_binding_handle(tmp_ctx,
9454                                                get_session_info_system(),
9455                                                p->msg_ctx,
9456                                                &b);
9457         if (!W_ERROR_IS_OK(result)) {
9458                 goto done;
9459         }
9460
9461         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9462         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9463             strequal(r->in.value_name, "ChangeId")) {
9464                 *r->out.type = REG_DWORD;
9465                 *r->out.needed = 4;
9466                 if (r->in.offered >= *r->out.needed) {
9467                         uint32_t changeid = 0;
9468
9469                         result = winreg_printer_get_changeid(tmp_ctx, b,
9470                                                              printer,
9471                                                              &changeid);
9472                         if (!W_ERROR_IS_OK(result)) {
9473                                 goto done;
9474                         }
9475
9476                         SIVAL(r->out.data, 0, changeid);
9477                         result = WERR_OK;
9478                 }
9479                 goto done;
9480         }
9481
9482         result = winreg_get_printer_dataex(tmp_ctx, b,
9483                                            printer,
9484                                            r->in.key_name,
9485                                            r->in.value_name,
9486                                            &val_type,
9487                                            &val_data,
9488                                            &val_size);
9489         if (!W_ERROR_IS_OK(result)) {
9490                 goto done;
9491         }
9492
9493         *r->out.needed = val_size;
9494         *r->out.type = val_type;
9495
9496         if (r->in.offered >= *r->out.needed) {
9497                 memcpy(r->out.data, val_data, val_size);
9498         }
9499
9500 done:
9501         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9502
9503         if (W_ERROR_IS_OK(result)) {
9504                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9505         }
9506
9507         talloc_free(tmp_ctx);
9508         return result;
9509 }
9510
9511 /****************************************************************
9512  _spoolss_SetPrinterDataEx
9513 ****************************************************************/
9514
9515 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9516                                  struct spoolss_SetPrinterDataEx *r)
9517 {
9518         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9519         int                     snum = 0;
9520         WERROR                  result = WERR_OK;
9521         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9522         char                    *oid_string;
9523         struct dcerpc_binding_handle *b;
9524         TALLOC_CTX *tmp_ctx;
9525
9526         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9527
9528         /* From MSDN documentation of SetPrinterDataEx: pass request to
9529            SetPrinterData if key is "PrinterDriverData" */
9530
9531         if (!Printer) {
9532                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9533                         OUR_HANDLE(r->in.handle)));
9534                 return WERR_BADFID;
9535         }
9536
9537         if (Printer->printer_type == SPLHND_SERVER) {
9538                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9539                         "Not implemented for server handles yet\n"));
9540                 return WERR_INVALID_PARAM;
9541         }
9542
9543         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9544                 return WERR_BADFID;
9545         }
9546
9547         /*
9548          * Access check : NT returns "access denied" if you make a
9549          * SetPrinterData call without the necessary privildge.
9550          * we were originally returning OK if nothing changed
9551          * which made Win2k issue **a lot** of SetPrinterData
9552          * when connecting to a printer  --jerry
9553          */
9554
9555         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9556                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9557                         "change denied by handle access permissions\n"));
9558                 return WERR_ACCESS_DENIED;
9559         }
9560
9561         tmp_ctx = talloc_new(p->mem_ctx);
9562         if (!tmp_ctx) {
9563                 return WERR_NOMEM;
9564         }
9565
9566         result = winreg_printer_binding_handle(tmp_ctx,
9567                                                get_session_info_system(),
9568                                                p->msg_ctx,
9569                                                &b);
9570         if (!W_ERROR_IS_OK(result)) {
9571                 goto done;
9572         }
9573
9574         result = winreg_get_printer(tmp_ctx, b,
9575                                     lp_servicename(snum),
9576                                     &pinfo2);
9577         if (!W_ERROR_IS_OK(result)) {
9578                 goto done;
9579         }
9580
9581         /* check for OID in valuename */
9582
9583         oid_string = strchr(r->in.value_name, ',');
9584         if (oid_string) {
9585                 *oid_string = '\0';
9586                 oid_string++;
9587         }
9588
9589         /* save the registry data */
9590
9591         result = winreg_set_printer_dataex(tmp_ctx, b,
9592                                            pinfo2->sharename,
9593                                            r->in.key_name,
9594                                            r->in.value_name,
9595                                            r->in.type,
9596                                            r->in.data,
9597                                            r->in.offered);
9598
9599         if (W_ERROR_IS_OK(result)) {
9600                 /* save the OID if one was specified */
9601                 if (oid_string) {
9602                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9603                                 r->in.key_name, SPOOL_OID_KEY);
9604                         if (!str) {
9605                                 result = WERR_NOMEM;
9606                                 goto done;
9607                         }
9608
9609                         /*
9610                          * I'm not checking the status here on purpose.  Don't know
9611                          * if this is right, but I'm returning the status from the
9612                          * previous set_printer_dataex() call.  I have no idea if
9613                          * this is right.    --jerry
9614                          */
9615                         winreg_set_printer_dataex(tmp_ctx, b,
9616                                                   pinfo2->sharename,
9617                                                   str,
9618                                                   r->in.value_name,
9619                                                   REG_SZ,
9620                                                   (uint8_t *) oid_string,
9621                                                   strlen(oid_string) + 1);
9622                 }
9623
9624                 result = winreg_printer_update_changeid(tmp_ctx, b,
9625                                                         lp_const_servicename(snum));
9626
9627         }
9628
9629 done:
9630         talloc_free(tmp_ctx);
9631         return result;
9632 }
9633
9634 /****************************************************************
9635  _spoolss_DeletePrinterDataEx
9636 ****************************************************************/
9637
9638 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9639                                     struct spoolss_DeletePrinterDataEx *r)
9640 {
9641         const char *printer;
9642         int             snum=0;
9643         WERROR          status = WERR_OK;
9644         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9645
9646         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9647
9648         if (!Printer) {
9649                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9650                         "Invalid handle (%s:%u:%u).\n",
9651                         OUR_HANDLE(r->in.handle)));
9652                 return WERR_BADFID;
9653         }
9654
9655         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9656                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9657                         "printer properties change denied by handle\n"));
9658                 return WERR_ACCESS_DENIED;
9659         }
9660
9661         if (!r->in.value_name || !r->in.key_name) {
9662                 return WERR_NOMEM;
9663         }
9664
9665         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9666                 return WERR_BADFID;
9667         }
9668         printer = lp_const_servicename(snum);
9669
9670         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9671                                               get_session_info_system(),
9672                                               p->msg_ctx,
9673                                               printer,
9674                                               r->in.key_name,
9675                                               r->in.value_name);
9676         if (W_ERROR_IS_OK(status)) {
9677                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9678                                                         get_session_info_system(),
9679                                                         p->msg_ctx,
9680                                                         printer);
9681         }
9682
9683         return status;
9684 }
9685
9686 /****************************************************************
9687  _spoolss_EnumPrinterKey
9688 ****************************************************************/
9689
9690 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9691                                struct spoolss_EnumPrinterKey *r)
9692 {
9693         uint32_t        num_keys;
9694         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9695         int             snum = 0;
9696         WERROR          result = WERR_BADFILE;
9697         const char **array = NULL;
9698         DATA_BLOB blob;
9699
9700         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9701
9702         if (!Printer) {
9703                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9704                         OUR_HANDLE(r->in.handle)));
9705                 return WERR_BADFID;
9706         }
9707
9708         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9709                 return WERR_BADFID;
9710         }
9711
9712         result = winreg_enum_printer_key_internal(p->mem_ctx,
9713                                          get_session_info_system(),
9714                                          p->msg_ctx,
9715                                          lp_const_servicename(snum),
9716                                          r->in.key_name,
9717                                          &num_keys,
9718                                          &array);
9719         if (!W_ERROR_IS_OK(result)) {
9720                 goto done;
9721         }
9722
9723         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9724                 result = WERR_NOMEM;
9725                 goto done;
9726         }
9727
9728         *r->out._ndr_size = r->in.offered / 2;
9729         *r->out.needed = blob.length;
9730
9731         if (r->in.offered < *r->out.needed) {
9732                 result = WERR_MORE_DATA;
9733         } else {
9734                 result = WERR_OK;
9735                 r->out.key_buffer->string_array = array;
9736         }
9737
9738  done:
9739         if (!W_ERROR_IS_OK(result)) {
9740                 TALLOC_FREE(array);
9741                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9742                         *r->out.needed = 0;
9743                 }
9744         }
9745
9746         return result;
9747 }
9748
9749 /****************************************************************
9750  _spoolss_DeletePrinterKey
9751 ****************************************************************/
9752
9753 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9754                                  struct spoolss_DeletePrinterKey *r)
9755 {
9756         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9757         int                     snum=0;
9758         WERROR                  status;
9759         const char *printer;
9760         struct dcerpc_binding_handle *b;
9761         TALLOC_CTX *tmp_ctx;
9762
9763         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9764
9765         if (!Printer) {
9766                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9767                         OUR_HANDLE(r->in.handle)));
9768                 return WERR_BADFID;
9769         }
9770
9771         /* if keyname == NULL, return error */
9772         if ( !r->in.key_name )
9773                 return WERR_INVALID_PARAM;
9774
9775         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9776                 return WERR_BADFID;
9777         }
9778
9779         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9780                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9781                         "printer properties change denied by handle\n"));
9782                 return WERR_ACCESS_DENIED;
9783         }
9784
9785         printer = lp_const_servicename(snum);
9786
9787         tmp_ctx = talloc_new(p->mem_ctx);
9788         if (!tmp_ctx) {
9789                 return WERR_NOMEM;
9790         }
9791
9792         status = winreg_printer_binding_handle(tmp_ctx,
9793                                                get_session_info_system(),
9794                                                p->msg_ctx,
9795                                                &b);
9796         if (!W_ERROR_IS_OK(status)) {
9797                 goto done;
9798         }
9799
9800         /* delete the key and all subkeys */
9801         status = winreg_delete_printer_key(tmp_ctx, b,
9802                                            printer,
9803                                            r->in.key_name);
9804         if (W_ERROR_IS_OK(status)) {
9805                 status = winreg_printer_update_changeid(tmp_ctx, b,
9806                                                         printer);
9807         }
9808
9809 done:
9810         talloc_free(tmp_ctx);
9811         return status;
9812 }
9813
9814 /****************************************************************
9815  _spoolss_EnumPrinterDataEx
9816 ****************************************************************/
9817
9818 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9819                                   struct spoolss_EnumPrinterDataEx *r)
9820 {
9821         uint32_t        count = 0;
9822         struct spoolss_PrinterEnumValues *info = NULL;
9823         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9824         int             snum;
9825         WERROR          result;
9826
9827         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9828
9829         *r->out.count = 0;
9830         *r->out.needed = 0;
9831         *r->out.info = NULL;
9832
9833         if (!Printer) {
9834                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9835                         OUR_HANDLE(r->in.handle)));
9836                 return WERR_BADFID;
9837         }
9838
9839         /*
9840          * first check for a keyname of NULL or "".  Win2k seems to send
9841          * this a lot and we should send back WERR_INVALID_PARAM
9842          * no need to spend time looking up the printer in this case.
9843          * --jerry
9844          */
9845
9846         if (!strlen(r->in.key_name)) {
9847                 result = WERR_INVALID_PARAM;
9848                 goto done;
9849         }
9850
9851         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9852                 return WERR_BADFID;
9853         }
9854
9855         /* now look for a match on the key name */
9856         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9857                                             get_session_info_system(),
9858                                             p->msg_ctx,
9859                                             lp_const_servicename(snum),
9860                                             r->in.key_name,
9861                                             &count,
9862                                             &info);
9863         if (!W_ERROR_IS_OK(result)) {
9864                 goto done;
9865         }
9866
9867 #if 0 /* FIXME - gd */
9868         /* housekeeping information in the reply */
9869
9870         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9871          * the hand marshalled container size is a multiple
9872          * of 4 bytes for RPC alignment.
9873          */
9874
9875         if (needed % 4) {
9876                 needed += 4-(needed % 4);
9877         }
9878 #endif
9879         *r->out.count   = count;
9880         *r->out.info    = info;
9881
9882  done:
9883         if (!W_ERROR_IS_OK(result)) {
9884                 return result;
9885         }
9886
9887         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9888                                                spoolss_EnumPrinterDataEx,
9889                                                *r->out.info,
9890                                                *r->out.count);
9891         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9892         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9893
9894         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9895 }
9896
9897 /****************************************************************************
9898 ****************************************************************************/
9899
9900 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9901                                                  const char *servername,
9902                                                  const char *environment,
9903                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9904 {
9905         WERROR werr;
9906         char *path = NULL;
9907
9908         werr = compose_spoolss_server_path(mem_ctx,
9909                                            servername,
9910                                            environment,
9911                                            SPOOLSS_PRTPROCS_PATH,
9912                                            &path);
9913         if (!W_ERROR_IS_OK(werr)) {
9914                 return werr;
9915         }
9916
9917         DEBUG(4,("print processor directory: [%s]\n", path));
9918
9919         r->directory_name = path;
9920
9921         return WERR_OK;
9922 }
9923
9924 /****************************************************************
9925  _spoolss_GetPrintProcessorDirectory
9926 ****************************************************************/
9927
9928 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9929                                            struct spoolss_GetPrintProcessorDirectory *r)
9930 {
9931         WERROR result;
9932         char *prnproc_share = NULL;
9933         bool prnproc_share_exists = false;
9934         int snum;
9935
9936         /* that's an [in out] buffer */
9937
9938         if (!r->in.buffer && (r->in.offered != 0)) {
9939                 return WERR_INVALID_PARAM;
9940         }
9941
9942         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9943                 r->in.level));
9944
9945         *r->out.needed = 0;
9946
9947         /* r->in.level is ignored */
9948
9949         /* We always should reply with a local print processor directory so that
9950          * users are not forced to have a [prnproc$] share on the Samba spoolss
9951          * server, if users decide to do so, lets announce it though - Guenther */
9952
9953         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9954         if (!prnproc_share) {
9955                 return WERR_NOMEM;
9956         }
9957         if (snum != -1) {
9958                 prnproc_share_exists = true;
9959         }
9960
9961         result = getprintprocessordirectory_level_1(p->mem_ctx,
9962                                                     prnproc_share_exists ? r->in.server : NULL,
9963                                                     r->in.environment,
9964                                                     &r->out.info->info1);
9965         if (!W_ERROR_IS_OK(result)) {
9966                 TALLOC_FREE(r->out.info);
9967                 return result;
9968         }
9969
9970         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9971                                                                                    r->out.info, r->in.level);
9972         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9973
9974         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9975 }
9976
9977 /*******************************************************************
9978  ********************************************************************/
9979
9980 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9981                                const char *dllname)
9982 {
9983         enum ndr_err_code ndr_err;
9984         struct spoolss_MonitorUi ui;
9985
9986         ui.dll_name = dllname;
9987
9988         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9989                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9990         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9991                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9992         }
9993         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9994 }
9995
9996 /*******************************************************************
9997  Streams the monitor UI DLL name in UNICODE
9998 *******************************************************************/
9999
10000 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10001                                struct security_token *token, DATA_BLOB *in,
10002                                DATA_BLOB *out, uint32_t *needed)
10003 {
10004         const char *dllname = "tcpmonui.dll";
10005
10006         *needed = (strlen(dllname)+1) * 2;
10007
10008         if (out->length < *needed) {
10009                 return WERR_INSUFFICIENT_BUFFER;
10010         }
10011
10012         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10013                 return WERR_NOMEM;
10014         }
10015
10016         return WERR_OK;
10017 }
10018
10019 /*******************************************************************
10020  ********************************************************************/
10021
10022 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10023                              struct spoolss_PortData1 *port1,
10024                              const DATA_BLOB *buf)
10025 {
10026         enum ndr_err_code ndr_err;
10027         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10028                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10029         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10030                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10031         }
10032         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10033 }
10034
10035 /*******************************************************************
10036  ********************************************************************/
10037
10038 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10039                              struct spoolss_PortData2 *port2,
10040                              const DATA_BLOB *buf)
10041 {
10042         enum ndr_err_code ndr_err;
10043         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10044                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10045         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10046                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10047         }
10048         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10049 }
10050
10051 /*******************************************************************
10052  Create a new TCP/IP port
10053 *******************************************************************/
10054
10055 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10056                              struct security_token *token, DATA_BLOB *in,
10057                              DATA_BLOB *out, uint32_t *needed)
10058 {
10059         struct spoolss_PortData1 port1;
10060         struct spoolss_PortData2 port2;
10061         char *device_uri = NULL;
10062         uint32_t version;
10063
10064         const char *portname;
10065         const char *hostaddress;
10066         const char *queue;
10067         uint32_t port_number;
10068         uint32_t protocol;
10069
10070         /* peek for spoolss_PortData version */
10071
10072         if (!in || (in->length < (128 + 4))) {
10073                 return WERR_GENERAL_FAILURE;
10074         }
10075
10076         version = IVAL(in->data, 128);
10077
10078         switch (version) {
10079                 case 1:
10080                         ZERO_STRUCT(port1);
10081
10082                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10083                                 return WERR_NOMEM;
10084                         }
10085
10086                         portname        = port1.portname;
10087                         hostaddress     = port1.hostaddress;
10088                         queue           = port1.queue;
10089                         protocol        = port1.protocol;
10090                         port_number     = port1.port_number;
10091
10092                         break;
10093                 case 2:
10094                         ZERO_STRUCT(port2);
10095
10096                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10097                                 return WERR_NOMEM;
10098                         }
10099
10100                         portname        = port2.portname;
10101                         hostaddress     = port2.hostaddress;
10102                         queue           = port2.queue;
10103                         protocol        = port2.protocol;
10104                         port_number     = port2.port_number;
10105
10106                         break;
10107                 default:
10108                         DEBUG(1,("xcvtcp_addport: "
10109                                 "unknown version of port_data: %d\n", version));
10110                         return WERR_UNKNOWN_PORT;
10111         }
10112
10113         /* create the device URI and call the add_port_hook() */
10114
10115         switch (protocol) {
10116         case PROTOCOL_RAWTCP_TYPE:
10117                 device_uri = talloc_asprintf(mem_ctx,
10118                                 "socket://%s:%d/", hostaddress,
10119                                 port_number);
10120                 break;
10121
10122         case PROTOCOL_LPR_TYPE:
10123                 device_uri = talloc_asprintf(mem_ctx,
10124                         "lpr://%s/%s", hostaddress, queue );
10125                 break;
10126
10127         default:
10128                 return WERR_UNKNOWN_PORT;
10129         }
10130
10131         if (!device_uri) {
10132                 return WERR_NOMEM;
10133         }
10134
10135         return add_port_hook(mem_ctx, token, portname, device_uri);
10136 }
10137
10138 /*******************************************************************
10139 *******************************************************************/
10140
10141 struct xcv_api_table xcvtcp_cmds[] = {
10142         { "MonitorUI",  xcvtcp_monitorui },
10143         { "AddPort",    xcvtcp_addport},
10144         { NULL,         NULL }
10145 };
10146
10147 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10148                                      struct security_token *token, const char *command,
10149                                      DATA_BLOB *inbuf,
10150                                      DATA_BLOB *outbuf,
10151                                      uint32_t *needed )
10152 {
10153         int i;
10154
10155         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10156
10157         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10158                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10159                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10160         }
10161
10162         return WERR_BADFUNC;
10163 }
10164
10165 /*******************************************************************
10166 *******************************************************************/
10167 #if 0   /* don't support management using the "Local Port" monitor */
10168
10169 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10170                                  struct security_token *token, DATA_BLOB *in,
10171                                  DATA_BLOB *out, uint32_t *needed)
10172 {
10173         const char *dllname = "localui.dll";
10174
10175         *needed = (strlen(dllname)+1) * 2;
10176
10177         if (out->length < *needed) {
10178                 return WERR_INSUFFICIENT_BUFFER;
10179         }
10180
10181         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10182                 return WERR_NOMEM;
10183         }
10184
10185         return WERR_OK;
10186 }
10187
10188 /*******************************************************************
10189 *******************************************************************/
10190
10191 struct xcv_api_table xcvlocal_cmds[] = {
10192         { "MonitorUI",  xcvlocal_monitorui },
10193         { NULL,         NULL }
10194 };
10195 #else
10196 struct xcv_api_table xcvlocal_cmds[] = {
10197         { NULL,         NULL }
10198 };
10199 #endif
10200
10201
10202
10203 /*******************************************************************
10204 *******************************************************************/
10205
10206 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10207                                        struct security_token *token, const char *command,
10208                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10209                                        uint32_t *needed)
10210 {
10211         int i;
10212
10213         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10214
10215         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10216                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10217                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10218         }
10219         return WERR_BADFUNC;
10220 }
10221
10222 /****************************************************************
10223  _spoolss_XcvData
10224 ****************************************************************/
10225
10226 WERROR _spoolss_XcvData(struct pipes_struct *p,
10227                         struct spoolss_XcvData *r)
10228 {
10229         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10230         DATA_BLOB out_data = data_blob_null;
10231         WERROR werror;
10232
10233         if (!Printer) {
10234                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10235                         OUR_HANDLE(r->in.handle)));
10236                 return WERR_BADFID;
10237         }
10238
10239         /* Has to be a handle to the TCP/IP port monitor */
10240
10241         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10242                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10243                 return WERR_BADFID;
10244         }
10245
10246         /* requires administrative access to the server */
10247
10248         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10249                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10250                 return WERR_ACCESS_DENIED;
10251         }
10252
10253         /* Allocate the outgoing buffer */
10254
10255         if (r->in.out_data_size) {
10256                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10257                 if (out_data.data == NULL) {
10258                         return WERR_NOMEM;
10259                 }
10260         }
10261
10262         switch ( Printer->printer_type ) {
10263         case SPLHND_PORTMON_TCP:
10264                 werror = process_xcvtcp_command(p->mem_ctx,
10265                                                 p->session_info->security_token,
10266                                                 r->in.function_name,
10267                                                 &r->in.in_data, &out_data,
10268                                                 r->out.needed);
10269                 break;
10270         case SPLHND_PORTMON_LOCAL:
10271                 werror = process_xcvlocal_command(p->mem_ctx,
10272                                                   p->session_info->security_token,
10273                                                   r->in.function_name,
10274                                                   &r->in.in_data, &out_data,
10275                                                   r->out.needed);
10276                 break;
10277         default:
10278                 werror = WERR_INVALID_PRINT_MONITOR;
10279         }
10280
10281         if (!W_ERROR_IS_OK(werror)) {
10282                 return werror;
10283         }
10284
10285         *r->out.status_code = 0;
10286
10287         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10288                 memcpy(r->out.out_data, out_data.data,
10289                         MIN(r->in.out_data_size, out_data.length));
10290         }
10291
10292         return WERR_OK;
10293 }
10294
10295 /****************************************************************
10296  _spoolss_AddPrintProcessor
10297 ****************************************************************/
10298
10299 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10300                                   struct spoolss_AddPrintProcessor *r)
10301 {
10302         /* for now, just indicate success and ignore the add.  We'll
10303            automatically set the winprint processor for printer
10304            entries later.  Used to debug the LexMark Optra S 1855 PCL
10305            driver --jerry */
10306
10307         return WERR_OK;
10308 }
10309
10310 /****************************************************************
10311  _spoolss_AddPort
10312 ****************************************************************/
10313
10314 WERROR _spoolss_AddPort(struct pipes_struct *p,
10315                         struct spoolss_AddPort *r)
10316 {
10317         /* do what w2k3 does */
10318
10319         return WERR_NOT_SUPPORTED;
10320 }
10321
10322 /****************************************************************
10323  _spoolss_GetPrinterDriver
10324 ****************************************************************/
10325
10326 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10327                                  struct spoolss_GetPrinterDriver *r)
10328 {
10329         p->rng_fault_state = true;
10330         return WERR_NOT_SUPPORTED;
10331 }
10332
10333 /****************************************************************
10334  _spoolss_ReadPrinter
10335 ****************************************************************/
10336
10337 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10338                             struct spoolss_ReadPrinter *r)
10339 {
10340         p->rng_fault_state = true;
10341         return WERR_NOT_SUPPORTED;
10342 }
10343
10344 /****************************************************************
10345  _spoolss_WaitForPrinterChange
10346 ****************************************************************/
10347
10348 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10349                                      struct spoolss_WaitForPrinterChange *r)
10350 {
10351         p->rng_fault_state = true;
10352         return WERR_NOT_SUPPORTED;
10353 }
10354
10355 /****************************************************************
10356  _spoolss_ConfigurePort
10357 ****************************************************************/
10358
10359 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10360                               struct spoolss_ConfigurePort *r)
10361 {
10362         p->rng_fault_state = true;
10363         return WERR_NOT_SUPPORTED;
10364 }
10365
10366 /****************************************************************
10367  _spoolss_DeletePort
10368 ****************************************************************/
10369
10370 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10371                            struct spoolss_DeletePort *r)
10372 {
10373         p->rng_fault_state = true;
10374         return WERR_NOT_SUPPORTED;
10375 }
10376
10377 /****************************************************************
10378  _spoolss_CreatePrinterIC
10379 ****************************************************************/
10380
10381 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10382                                 struct spoolss_CreatePrinterIC *r)
10383 {
10384         p->rng_fault_state = true;
10385         return WERR_NOT_SUPPORTED;
10386 }
10387
10388 /****************************************************************
10389  _spoolss_PlayGDIScriptOnPrinterIC
10390 ****************************************************************/
10391
10392 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10393                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10394 {
10395         p->rng_fault_state = true;
10396         return WERR_NOT_SUPPORTED;
10397 }
10398
10399 /****************************************************************
10400  _spoolss_DeletePrinterIC
10401 ****************************************************************/
10402
10403 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10404                                 struct spoolss_DeletePrinterIC *r)
10405 {
10406         p->rng_fault_state = true;
10407         return WERR_NOT_SUPPORTED;
10408 }
10409
10410 /****************************************************************
10411  _spoolss_AddPrinterConnection
10412 ****************************************************************/
10413
10414 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10415                                      struct spoolss_AddPrinterConnection *r)
10416 {
10417         p->rng_fault_state = true;
10418         return WERR_NOT_SUPPORTED;
10419 }
10420
10421 /****************************************************************
10422  _spoolss_DeletePrinterConnection
10423 ****************************************************************/
10424
10425 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10426                                         struct spoolss_DeletePrinterConnection *r)
10427 {
10428         p->rng_fault_state = true;
10429         return WERR_NOT_SUPPORTED;
10430 }
10431
10432 /****************************************************************
10433  _spoolss_PrinterMessageBox
10434 ****************************************************************/
10435
10436 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10437                                   struct spoolss_PrinterMessageBox *r)
10438 {
10439         p->rng_fault_state = true;
10440         return WERR_NOT_SUPPORTED;
10441 }
10442
10443 /****************************************************************
10444  _spoolss_AddMonitor
10445 ****************************************************************/
10446
10447 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10448                            struct spoolss_AddMonitor *r)
10449 {
10450         p->rng_fault_state = true;
10451         return WERR_NOT_SUPPORTED;
10452 }
10453
10454 /****************************************************************
10455  _spoolss_DeleteMonitor
10456 ****************************************************************/
10457
10458 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10459                               struct spoolss_DeleteMonitor *r)
10460 {
10461         p->rng_fault_state = true;
10462         return WERR_NOT_SUPPORTED;
10463 }
10464
10465 /****************************************************************
10466  _spoolss_DeletePrintProcessor
10467 ****************************************************************/
10468
10469 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10470                                      struct spoolss_DeletePrintProcessor *r)
10471 {
10472         p->rng_fault_state = true;
10473         return WERR_NOT_SUPPORTED;
10474 }
10475
10476 /****************************************************************
10477  _spoolss_AddPrintProvidor
10478 ****************************************************************/
10479
10480 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10481                                  struct spoolss_AddPrintProvidor *r)
10482 {
10483         p->rng_fault_state = true;
10484         return WERR_NOT_SUPPORTED;
10485 }
10486
10487 /****************************************************************
10488  _spoolss_DeletePrintProvidor
10489 ****************************************************************/
10490
10491 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10492                                     struct spoolss_DeletePrintProvidor *r)
10493 {
10494         p->rng_fault_state = true;
10495         return WERR_NOT_SUPPORTED;
10496 }
10497
10498 /****************************************************************
10499  _spoolss_FindFirstPrinterChangeNotification
10500 ****************************************************************/
10501
10502 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10503                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10504 {
10505         p->rng_fault_state = true;
10506         return WERR_NOT_SUPPORTED;
10507 }
10508
10509 /****************************************************************
10510  _spoolss_FindNextPrinterChangeNotification
10511 ****************************************************************/
10512
10513 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10514                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10515 {
10516         p->rng_fault_state = true;
10517         return WERR_NOT_SUPPORTED;
10518 }
10519
10520 /****************************************************************
10521  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10522 ****************************************************************/
10523
10524 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10525                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10526 {
10527         p->rng_fault_state = true;
10528         return WERR_NOT_SUPPORTED;
10529 }
10530
10531 /****************************************************************
10532  _spoolss_ReplyOpenPrinter
10533 ****************************************************************/
10534
10535 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10536                                  struct spoolss_ReplyOpenPrinter *r)
10537 {
10538         p->rng_fault_state = true;
10539         return WERR_NOT_SUPPORTED;
10540 }
10541
10542 /****************************************************************
10543  _spoolss_RouterReplyPrinter
10544 ****************************************************************/
10545
10546 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10547                                    struct spoolss_RouterReplyPrinter *r)
10548 {
10549         p->rng_fault_state = true;
10550         return WERR_NOT_SUPPORTED;
10551 }
10552
10553 /****************************************************************
10554  _spoolss_ReplyClosePrinter
10555 ****************************************************************/
10556
10557 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10558                                   struct spoolss_ReplyClosePrinter *r)
10559 {
10560         p->rng_fault_state = true;
10561         return WERR_NOT_SUPPORTED;
10562 }
10563
10564 /****************************************************************
10565  _spoolss_AddPortEx
10566 ****************************************************************/
10567
10568 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10569                           struct spoolss_AddPortEx *r)
10570 {
10571         p->rng_fault_state = true;
10572         return WERR_NOT_SUPPORTED;
10573 }
10574
10575 /****************************************************************
10576  _spoolss_RouterFindFirstPrinterChangeNotification
10577 ****************************************************************/
10578
10579 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10580                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10581 {
10582         p->rng_fault_state = true;
10583         return WERR_NOT_SUPPORTED;
10584 }
10585
10586 /****************************************************************
10587  _spoolss_SpoolerInit
10588 ****************************************************************/
10589
10590 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10591                             struct spoolss_SpoolerInit *r)
10592 {
10593         p->rng_fault_state = true;
10594         return WERR_NOT_SUPPORTED;
10595 }
10596
10597 /****************************************************************
10598  _spoolss_ResetPrinterEx
10599 ****************************************************************/
10600
10601 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10602                                struct spoolss_ResetPrinterEx *r)
10603 {
10604         p->rng_fault_state = true;
10605         return WERR_NOT_SUPPORTED;
10606 }
10607
10608 /****************************************************************
10609  _spoolss_RouterReplyPrinterEx
10610 ****************************************************************/
10611
10612 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10613                                      struct spoolss_RouterReplyPrinterEx *r)
10614 {
10615         p->rng_fault_state = true;
10616         return WERR_NOT_SUPPORTED;
10617 }
10618
10619 /****************************************************************
10620  _spoolss_44
10621 ****************************************************************/
10622
10623 WERROR _spoolss_44(struct pipes_struct *p,
10624                    struct spoolss_44 *r)
10625 {
10626         p->rng_fault_state = true;
10627         return WERR_NOT_SUPPORTED;
10628 }
10629
10630 /****************************************************************
10631  _spoolss_SetPort
10632 ****************************************************************/
10633
10634 WERROR _spoolss_SetPort(struct pipes_struct *p,
10635                         struct spoolss_SetPort *r)
10636 {
10637         p->rng_fault_state = true;
10638         return WERR_NOT_SUPPORTED;
10639 }
10640
10641 /****************************************************************
10642  _spoolss_4a
10643 ****************************************************************/
10644
10645 WERROR _spoolss_4a(struct pipes_struct *p,
10646                    struct spoolss_4a *r)
10647 {
10648         p->rng_fault_state = true;
10649         return WERR_NOT_SUPPORTED;
10650 }
10651
10652 /****************************************************************
10653  _spoolss_4b
10654 ****************************************************************/
10655
10656 WERROR _spoolss_4b(struct pipes_struct *p,
10657                    struct spoolss_4b *r)
10658 {
10659         p->rng_fault_state = true;
10660         return WERR_NOT_SUPPORTED;
10661 }
10662
10663 /****************************************************************
10664  _spoolss_4c
10665 ****************************************************************/
10666
10667 WERROR _spoolss_4c(struct pipes_struct *p,
10668                    struct spoolss_4c *r)
10669 {
10670         p->rng_fault_state = true;
10671         return WERR_NOT_SUPPORTED;
10672 }
10673
10674 /****************************************************************
10675  _spoolss_53
10676 ****************************************************************/
10677
10678 WERROR _spoolss_53(struct pipes_struct *p,
10679                    struct spoolss_53 *r)
10680 {
10681         p->rng_fault_state = true;
10682         return WERR_NOT_SUPPORTED;
10683 }
10684
10685 /****************************************************************
10686  _spoolss_AddPerMachineConnection
10687 ****************************************************************/
10688
10689 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10690                                         struct spoolss_AddPerMachineConnection *r)
10691 {
10692         p->rng_fault_state = true;
10693         return WERR_NOT_SUPPORTED;
10694 }
10695
10696 /****************************************************************
10697  _spoolss_DeletePerMachineConnection
10698 ****************************************************************/
10699
10700 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10701                                            struct spoolss_DeletePerMachineConnection *r)
10702 {
10703         p->rng_fault_state = true;
10704         return WERR_NOT_SUPPORTED;
10705 }
10706
10707 /****************************************************************
10708  _spoolss_EnumPerMachineConnections
10709 ****************************************************************/
10710
10711 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10712                                           struct spoolss_EnumPerMachineConnections *r)
10713 {
10714         p->rng_fault_state = true;
10715         return WERR_NOT_SUPPORTED;
10716 }
10717
10718 /****************************************************************
10719  _spoolss_5a
10720 ****************************************************************/
10721
10722 WERROR _spoolss_5a(struct pipes_struct *p,
10723                    struct spoolss_5a *r)
10724 {
10725         p->rng_fault_state = true;
10726         return WERR_NOT_SUPPORTED;
10727 }
10728
10729 /****************************************************************
10730  _spoolss_5b
10731 ****************************************************************/
10732
10733 WERROR _spoolss_5b(struct pipes_struct *p,
10734                    struct spoolss_5b *r)
10735 {
10736         p->rng_fault_state = true;
10737         return WERR_NOT_SUPPORTED;
10738 }
10739
10740 /****************************************************************
10741  _spoolss_5c
10742 ****************************************************************/
10743
10744 WERROR _spoolss_5c(struct pipes_struct *p,
10745                    struct spoolss_5c *r)
10746 {
10747         p->rng_fault_state = true;
10748         return WERR_NOT_SUPPORTED;
10749 }
10750
10751 /****************************************************************
10752  _spoolss_5d
10753 ****************************************************************/
10754
10755 WERROR _spoolss_5d(struct pipes_struct *p,
10756                    struct spoolss_5d *r)
10757 {
10758         p->rng_fault_state = true;
10759         return WERR_NOT_SUPPORTED;
10760 }
10761
10762 /****************************************************************
10763  _spoolss_5e
10764 ****************************************************************/
10765
10766 WERROR _spoolss_5e(struct pipes_struct *p,
10767                    struct spoolss_5e *r)
10768 {
10769         p->rng_fault_state = true;
10770         return WERR_NOT_SUPPORTED;
10771 }
10772
10773 /****************************************************************
10774  _spoolss_5f
10775 ****************************************************************/
10776
10777 WERROR _spoolss_5f(struct pipes_struct *p,
10778                    struct spoolss_5f *r)
10779 {
10780         p->rng_fault_state = true;
10781         return WERR_NOT_SUPPORTED;
10782 }
10783
10784 /****************************************************************
10785  _spoolss_60
10786 ****************************************************************/
10787
10788 WERROR _spoolss_60(struct pipes_struct *p,
10789                    struct spoolss_60 *r)
10790 {
10791         p->rng_fault_state = true;
10792         return WERR_NOT_SUPPORTED;
10793 }
10794
10795 /****************************************************************
10796  _spoolss_61
10797 ****************************************************************/
10798
10799 WERROR _spoolss_61(struct pipes_struct *p,
10800                    struct spoolss_61 *r)
10801 {
10802         p->rng_fault_state = true;
10803         return WERR_NOT_SUPPORTED;
10804 }
10805
10806 /****************************************************************
10807  _spoolss_62
10808 ****************************************************************/
10809
10810 WERROR _spoolss_62(struct pipes_struct *p,
10811                    struct spoolss_62 *r)
10812 {
10813         p->rng_fault_state = true;
10814         return WERR_NOT_SUPPORTED;
10815 }
10816
10817 /****************************************************************
10818  _spoolss_63
10819 ****************************************************************/
10820
10821 WERROR _spoolss_63(struct pipes_struct *p,
10822                    struct spoolss_63 *r)
10823 {
10824         p->rng_fault_state = true;
10825         return WERR_NOT_SUPPORTED;
10826 }
10827
10828 /****************************************************************
10829  _spoolss_64
10830 ****************************************************************/
10831
10832 WERROR _spoolss_64(struct pipes_struct *p,
10833                    struct spoolss_64 *r)
10834 {
10835         p->rng_fault_state = true;
10836         return WERR_NOT_SUPPORTED;
10837 }
10838
10839 /****************************************************************
10840  _spoolss_65
10841 ****************************************************************/
10842
10843 WERROR _spoolss_65(struct pipes_struct *p,
10844                    struct spoolss_65 *r)
10845 {
10846         p->rng_fault_state = true;
10847         return WERR_NOT_SUPPORTED;
10848 }
10849
10850 /****************************************************************
10851  _spoolss_GetCorePrinterDrivers
10852 ****************************************************************/
10853
10854 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10855                                       struct spoolss_GetCorePrinterDrivers *r)
10856 {
10857         p->rng_fault_state = true;
10858         return WERR_NOT_SUPPORTED;
10859 }
10860
10861 /****************************************************************
10862  _spoolss_67
10863 ****************************************************************/
10864
10865 WERROR _spoolss_67(struct pipes_struct *p,
10866                    struct spoolss_67 *r)
10867 {
10868         p->rng_fault_state = true;
10869         return WERR_NOT_SUPPORTED;
10870 }
10871
10872 /****************************************************************
10873  _spoolss_GetPrinterDriverPackagePath
10874 ****************************************************************/
10875
10876 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10877                                             struct spoolss_GetPrinterDriverPackagePath *r)
10878 {
10879         p->rng_fault_state = true;
10880         return WERR_NOT_SUPPORTED;
10881 }
10882
10883 /****************************************************************
10884  _spoolss_69
10885 ****************************************************************/
10886
10887 WERROR _spoolss_69(struct pipes_struct *p,
10888                    struct spoolss_69 *r)
10889 {
10890         p->rng_fault_state = true;
10891         return WERR_NOT_SUPPORTED;
10892 }
10893
10894 /****************************************************************
10895  _spoolss_6a
10896 ****************************************************************/
10897
10898 WERROR _spoolss_6a(struct pipes_struct *p,
10899                    struct spoolss_6a *r)
10900 {
10901         p->rng_fault_state = true;
10902         return WERR_NOT_SUPPORTED;
10903 }
10904
10905 /****************************************************************
10906  _spoolss_6b
10907 ****************************************************************/
10908
10909 WERROR _spoolss_6b(struct pipes_struct *p,
10910                    struct spoolss_6b *r)
10911 {
10912         p->rng_fault_state = true;
10913         return WERR_NOT_SUPPORTED;
10914 }
10915
10916 /****************************************************************
10917  _spoolss_6c
10918 ****************************************************************/
10919
10920 WERROR _spoolss_6c(struct pipes_struct *p,
10921                    struct spoolss_6c *r)
10922 {
10923         p->rng_fault_state = true;
10924         return WERR_NOT_SUPPORTED;
10925 }
10926
10927 /****************************************************************
10928  _spoolss_6d
10929 ****************************************************************/
10930
10931 WERROR _spoolss_6d(struct pipes_struct *p,
10932                    struct spoolss_6d *r)
10933 {
10934         p->rng_fault_state = true;
10935         return WERR_NOT_SUPPORTED;
10936 }