Fix bug 9900: is_printer_published GUID retrieval
[obnox/samba/samba-obnox.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "include/printing.h"
42 #include "secrets.h"
43 #include "../librpc/gen_ndr/netlogon.h"
44 #include "rpc_misc.h"
45 #include "printing/notify.h"
46 #include "serverid.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "smbd/globals.h"
50 #include "auth.h"
51 #include "messages.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
53 #include "util_tdb.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
58 #include "../libcli/smb/smbXcli_base.h"
59
60 /* macros stolen from s4 spoolss server */
61 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
62         ((info)?ndr_size_##fn(info, level, 0):0)
63
64 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
65         ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
66
67 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
68         ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
69
70 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
71
72 #undef DBGC_CLASS
73 #define DBGC_CLASS DBGC_RPC_SRV
74
75 #ifndef MAX_OPEN_PRINTER_EXS
76 #define MAX_OPEN_PRINTER_EXS 50
77 #endif
78
79 struct notify_back_channel;
80
81 /* structure to store the printer handles */
82 /* and a reference to what it's pointing to */
83 /* and the notify info asked about */
84 /* that's the central struct */
85 struct printer_handle {
86         struct printer_handle *prev, *next;
87         bool document_started;
88         bool page_started;
89         uint32 jobid; /* jobid in printing backend */
90         int printer_type;
91         const char *servername;
92         fstring sharename;
93         uint32 type;
94         uint32 access_granted;
95         struct {
96                 uint32 flags;
97                 uint32 options;
98                 fstring localmachine;
99                 uint32 printerlocal;
100                 struct spoolss_NotifyOption *option;
101                 struct policy_handle cli_hnd;
102                 struct notify_back_channel *cli_chan;
103                 uint32 change;
104                 /* are we in a FindNextPrinterChangeNotify() call? */
105                 bool fnpcn;
106                 struct messaging_context *msg_ctx;
107         } notify;
108         struct {
109                 fstring machine;
110                 fstring user;
111         } client;
112
113         /* devmode sent in the OpenPrinter() call */
114         struct spoolss_DeviceMode *devmode;
115
116         /* TODO cache the printer info2 structure */
117         struct spoolss_PrinterInfo2 *info2;
118
119 };
120
121 static struct printer_handle *printers_list;
122
123 struct printer_session_counter {
124         struct printer_session_counter *next;
125         struct printer_session_counter *prev;
126
127         int snum;
128         uint32_t counter;
129 };
130
131 static struct printer_session_counter *counter_list;
132
133 struct notify_back_channel {
134         struct notify_back_channel *prev, *next;
135
136         /* associated client */
137         struct sockaddr_storage client_address;
138
139         /* print notify back-channel pipe handle*/
140         struct rpc_pipe_client *cli_pipe;
141         uint32_t active_connections;
142 };
143
144 static struct notify_back_channel *back_channels;
145
146 /* Map generic permissions to printer object specific permissions */
147
148 const struct standard_mapping printer_std_mapping = {
149         PRINTER_READ,
150         PRINTER_WRITE,
151         PRINTER_EXECUTE,
152         PRINTER_ALL_ACCESS
153 };
154
155 /* Map generic permissions to print server object specific permissions */
156
157 const struct standard_mapping printserver_std_mapping = {
158         SERVER_READ,
159         SERVER_WRITE,
160         SERVER_EXECUTE,
161         SERVER_ALL_ACCESS
162 };
163
164 /* API table for Xcv Monitor functions */
165
166 struct xcv_api_table {
167         const char *name;
168         WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
169 };
170
171 static void prune_printername_cache(void);
172
173 /********************************************************************
174  * Canonicalize servername.
175  ********************************************************************/
176
177 static const char *canon_servername(const char *servername)
178 {
179         const char *pservername = servername;
180         while (*pservername == '\\') {
181                 pservername++;
182         }
183         return pservername;
184 }
185
186 /* translate between internal status numbers and NT status numbers */
187 static int nt_printj_status(int v)
188 {
189         switch (v) {
190         case LPQ_QUEUED:
191                 return 0;
192         case LPQ_PAUSED:
193                 return JOB_STATUS_PAUSED;
194         case LPQ_SPOOLING:
195                 return JOB_STATUS_SPOOLING;
196         case LPQ_PRINTING:
197                 return JOB_STATUS_PRINTING;
198         case LPQ_ERROR:
199                 return JOB_STATUS_ERROR;
200         case LPQ_DELETING:
201                 return JOB_STATUS_DELETING;
202         case LPQ_OFFLINE:
203                 return JOB_STATUS_OFFLINE;
204         case LPQ_PAPEROUT:
205                 return JOB_STATUS_PAPEROUT;
206         case LPQ_PRINTED:
207                 return JOB_STATUS_PRINTED;
208         case LPQ_DELETED:
209                 return JOB_STATUS_DELETED;
210         case LPQ_BLOCKED:
211                 return JOB_STATUS_BLOCKED_DEVQ;
212         case LPQ_USER_INTERVENTION:
213                 return JOB_STATUS_USER_INTERVENTION;
214         }
215         return 0;
216 }
217
218 static int nt_printq_status(int v)
219 {
220         switch (v) {
221         case LPQ_PAUSED:
222                 return PRINTER_STATUS_PAUSED;
223         case LPQ_QUEUED:
224         case LPQ_SPOOLING:
225         case LPQ_PRINTING:
226                 return 0;
227         }
228         return 0;
229 }
230
231 /***************************************************************************
232  Disconnect from the client
233 ****************************************************************************/
234
235 static void srv_spoolss_replycloseprinter(int snum,
236                                           struct printer_handle *prn_hnd)
237 {
238         WERROR result;
239         NTSTATUS status;
240
241         /*
242          * Tell the specific printing tdb we no longer want messages for this printer
243          * by deregistering our PID.
244          */
245
246         if (!print_notify_deregister_pid(snum)) {
247                 DEBUG(0, ("Failed to register our pid for printer %s\n",
248                           lp_const_servicename(snum)));
249         }
250
251         /* weird if the test succeeds !!! */
252         if (prn_hnd->notify.cli_chan == NULL ||
253             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
254             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
255             prn_hnd->notify.cli_chan->active_connections == 0) {
256                 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
257                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
258                 TALLOC_FREE(prn_hnd->notify.cli_chan);
259                 return;
260         }
261
262         status = dcerpc_spoolss_ReplyClosePrinter(
263                                         prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
264                                         talloc_tos(),
265                                         &prn_hnd->notify.cli_hnd,
266                                         &result);
267         if (!NT_STATUS_IS_OK(status)) {
268                 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
269                           nt_errstr(status)));
270                 result = ntstatus_to_werror(status);
271         } else if (!W_ERROR_IS_OK(result)) {
272                 DEBUG(0, ("reply_close_printer failed [%s].\n",
273                           win_errstr(result)));
274         }
275
276         /* if it's the last connection, deconnect the IPC$ share */
277         if (prn_hnd->notify.cli_chan->active_connections == 1) {
278
279                 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
280                 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
281                 TALLOC_FREE(prn_hnd->notify.cli_chan);
282
283                 if (prn_hnd->notify.msg_ctx != NULL) {
284                         messaging_deregister(prn_hnd->notify.msg_ctx,
285                                              MSG_PRINTER_NOTIFY2, NULL);
286                 }
287         }
288
289         if (prn_hnd->notify.cli_chan) {
290                 prn_hnd->notify.cli_chan->active_connections--;
291                 prn_hnd->notify.cli_chan = NULL;
292         }
293 }
294
295 /****************************************************************************
296  Functions to free a printer entry datastruct.
297 ****************************************************************************/
298
299 static int printer_entry_destructor(struct printer_handle *Printer)
300 {
301         if (Printer->notify.cli_chan != NULL &&
302             Printer->notify.cli_chan->active_connections > 0) {
303                 int snum = -1;
304
305                 switch(Printer->printer_type) {
306                 case SPLHND_SERVER:
307                         srv_spoolss_replycloseprinter(snum, Printer);
308                         break;
309
310                 case SPLHND_PRINTER:
311                         snum = print_queue_snum(Printer->sharename);
312                         if (snum != -1) {
313                                 srv_spoolss_replycloseprinter(snum, Printer);
314                         }
315                         break;
316                 default:
317                         break;
318                 }
319         }
320
321         Printer->notify.flags=0;
322         Printer->notify.options=0;
323         Printer->notify.localmachine[0]='\0';
324         Printer->notify.printerlocal=0;
325         TALLOC_FREE(Printer->notify.option);
326         TALLOC_FREE(Printer->devmode);
327
328         /* Remove from the internal list. */
329         DLIST_REMOVE(printers_list, Printer);
330         return 0;
331 }
332
333 /****************************************************************************
334   find printer index by handle
335 ****************************************************************************/
336
337 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
338                                                         struct policy_handle *hnd)
339 {
340         struct printer_handle *find_printer = NULL;
341
342         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
343                 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
344                 return NULL;
345         }
346
347         return find_printer;
348 }
349
350 /****************************************************************************
351  Close printer index by handle.
352 ****************************************************************************/
353
354 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
355 {
356         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
357
358         if (!Printer) {
359                 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
360                         OUR_HANDLE(hnd)));
361                 return false;
362         }
363
364         close_policy_hnd(p, hnd);
365
366         return true;
367 }
368
369 /****************************************************************************
370  Delete a printer given a handle.
371 ****************************************************************************/
372
373 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
374                                   const char *sharename,
375                                   struct messaging_context *msg_ctx)
376 {
377         char *cmd = lp_deleteprinter_cmd(talloc_tos());
378         char *command = NULL;
379         int ret;
380         bool is_print_op = false;
381
382         /* can't fail if we don't try */
383
384         if ( !*cmd )
385                 return WERR_OK;
386
387         command = talloc_asprintf(ctx,
388                         "%s \"%s\"",
389                         cmd, sharename);
390         if (!command) {
391                 return WERR_NOMEM;
392         }
393         if ( token )
394                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
395
396         DEBUG(10,("Running [%s]\n", command));
397
398         /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
399
400         if ( is_print_op )
401                 become_root();
402
403         if ( (ret = smbrun(command, NULL)) == 0 ) {
404                 /* Tell everyone we updated smb.conf. */
405                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
406         }
407
408         if ( is_print_op )
409                 unbecome_root();
410
411         /********** END SePrintOperatorPrivlege BLOCK **********/
412
413         DEBUGADD(10,("returned [%d]\n", ret));
414
415         TALLOC_FREE(command);
416
417         if (ret != 0)
418                 return WERR_BADFID; /* What to return here? */
419
420         return WERR_OK;
421 }
422
423 /****************************************************************************
424  Delete a printer given a handle.
425 ****************************************************************************/
426
427 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
428 {
429         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
430         WERROR result;
431
432         if (!Printer) {
433                 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
434                         OUR_HANDLE(hnd)));
435                 return WERR_BADFID;
436         }
437
438         /*
439          * It turns out that Windows allows delete printer on a handle
440          * opened by an admin user, then used on a pipe handle created
441          * by an anonymous user..... but they're working on security.... riiight !
442          * JRA.
443          */
444
445         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
446                 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
447                 return WERR_ACCESS_DENIED;
448         }
449
450         /* this does not need a become root since the access check has been
451            done on the handle already */
452
453         result = winreg_delete_printer_key_internal(p->mem_ctx,
454                                            get_session_info_system(),
455                                            p->msg_ctx,
456                                            Printer->sharename,
457                                            "");
458         if (!W_ERROR_IS_OK(result)) {
459                 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
460                 return WERR_BADFID;
461         }
462
463         result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
464                                      Printer->sharename, p->msg_ctx);
465         if (!W_ERROR_IS_OK(result)) {
466                 return result;
467         }
468         prune_printername_cache();
469         return WERR_OK;
470 }
471
472 /****************************************************************************
473  Return the snum of a printer corresponding to an handle.
474 ****************************************************************************/
475
476 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
477                              int *number, struct share_params **params)
478 {
479         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
480
481         if (!Printer) {
482                 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
483                         OUR_HANDLE(hnd)));
484                 return false;
485         }
486
487         switch (Printer->printer_type) {
488                 case SPLHND_PRINTER:
489                         DEBUG(4,("short name:%s\n", Printer->sharename));
490                         *number = print_queue_snum(Printer->sharename);
491                         return (*number != -1);
492                 case SPLHND_SERVER:
493                         return false;
494                 default:
495                         return false;
496         }
497 }
498
499 /****************************************************************************
500  Set printer handle type.
501  Check if it's \\server or \\server\printer
502 ****************************************************************************/
503
504 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
505 {
506         DEBUG(3,("Setting printer type=%s\n", handlename));
507
508         /* it's a print server */
509         if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
510                 DEBUGADD(4,("Printer is a print server\n"));
511                 Printer->printer_type = SPLHND_SERVER;
512         }
513         /* it's a printer (set_printer_hnd_name() will handle port monitors */
514         else {
515                 DEBUGADD(4,("Printer is a printer\n"));
516                 Printer->printer_type = SPLHND_PRINTER;
517         }
518
519         return true;
520 }
521
522 static void prune_printername_cache_fn(const char *key, const char *value,
523                                        time_t timeout, void *private_data)
524 {
525         gencache_del(key);
526 }
527
528 static void prune_printername_cache(void)
529 {
530         gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
531 }
532
533 /****************************************************************************
534  Set printer handle name..  Accept names like \\server, \\server\printer,
535  \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port"    See
536  the MSDN docs regarding OpenPrinter() for details on the XcvData() and
537  XcvDataPort() interface.
538 ****************************************************************************/
539
540 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
541                                    const struct auth_session_info *session_info,
542                                    struct messaging_context *msg_ctx,
543                                    struct printer_handle *Printer,
544                                    const char *handlename)
545 {
546         int snum;
547         int n_services=lp_numservices();
548         char *aprinter;
549         const char *printername;
550         const char *servername = NULL;
551         fstring sname;
552         bool found = false;
553         struct spoolss_PrinterInfo2 *info2 = NULL;
554         WERROR result;
555         char *p;
556
557         /*
558          * Hopefully nobody names his printers like this. Maybe \ or ,
559          * are illegal in printer names even?
560          */
561         const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
562         char *cache_key;
563         char *tmp;
564
565         DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
566                 (unsigned long)strlen(handlename)));
567
568         aprinter = discard_const_p(char, handlename);
569         if ( *handlename == '\\' ) {
570                 servername = canon_servername(handlename);
571                 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
572                         *aprinter = '\0';
573                         aprinter++;
574                 }
575                 if (!is_myname_or_ipaddr(servername)) {
576                         return WERR_INVALID_PRINTER_NAME;
577                 }
578                 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
579                 if (Printer->servername == NULL) {
580                         return WERR_NOMEM;
581                 }
582         }
583
584         if (Printer->printer_type == SPLHND_SERVER) {
585                 return WERR_OK;
586         }
587
588         if (Printer->printer_type != SPLHND_PRINTER) {
589                 return WERR_INVALID_HANDLE;
590         }
591
592         DEBUGADD(5, ("searching for [%s]\n", aprinter));
593
594         p = strchr(aprinter, ',');
595         if (p != NULL) {
596                 char *p2 = p;
597                 p++;
598                 if (*p == ' ') {
599                         p++;
600                 }
601                 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
602                         *p2 = '\0';
603                 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
604                         *p2 = '\0';
605                 }
606         }
607
608         if (p) {
609                 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
610         }
611
612         /* check for the Port Monitor Interface */
613         if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
614                 Printer->printer_type = SPLHND_PORTMON_TCP;
615                 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
616                 found = true;
617         }
618         else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
619                 Printer->printer_type = SPLHND_PORTMON_LOCAL;
620                 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
621                 found = true;
622         }
623
624         /*
625          * With hundreds of printers, the "for" loop iterating all
626          * shares can be quite expensive, as it is done on every
627          * OpenPrinter. The loop maps "aprinter" to "sname", the
628          * result of which we cache in gencache.
629          */
630
631         cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
632                                     aprinter);
633         if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
634
635                 found = (strcmp(tmp, printer_not_found) != 0);
636                 if (!found) {
637                         DEBUG(4, ("Printer %s not found\n", aprinter));
638                         SAFE_FREE(tmp);
639                         return WERR_INVALID_PRINTER_NAME;
640                 }
641                 fstrcpy(sname, tmp);
642                 SAFE_FREE(tmp);
643         }
644
645         /* Search all sharenames first as this is easier than pulling
646            the printer_info_2 off of disk. Don't use find_service() since
647            that calls out to map_username() */
648
649         /* do another loop to look for printernames */
650         for (snum = 0; !found && snum < n_services; snum++) {
651                 const char *printer = lp_const_servicename(snum);
652
653                 /* no point going on if this is not a printer */
654                 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
655                         continue;
656                 }
657
658                 /* ignore [printers] share */
659                 if (strequal(printer, "printers")) {
660                         continue;
661                 }
662
663                 fstrcpy(sname, printer);
664                 if (strequal(aprinter, printer)) {
665                         found = true;
666                         break;
667                 }
668
669                 /* no point looking up the printer object if
670                    we aren't allowing printername != sharename */
671                 if (lp_force_printername(snum)) {
672                         continue;
673                 }
674
675                 result = winreg_get_printer_internal(mem_ctx,
676                                             session_info,
677                                             msg_ctx,
678                                             sname,
679                                             &info2);
680                 if ( !W_ERROR_IS_OK(result) ) {
681                         DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
682                                  sname, win_errstr(result)));
683                         continue;
684                 }
685
686                 printername = strrchr(info2->printername, '\\');
687                 if (printername == NULL) {
688                         printername = info2->printername;
689                 } else {
690                         printername++;
691                 }
692
693                 if (strequal(printername, aprinter)) {
694                         found = true;
695                         break;
696                 }
697
698                 DEBUGADD(10, ("printername: %s\n", printername));
699
700                 TALLOC_FREE(info2);
701         }
702
703         if ( !found ) {
704                 if (cache_key != NULL) {
705                         gencache_set(cache_key, printer_not_found,
706                                      time(NULL)+300);
707                         TALLOC_FREE(cache_key);
708                 }
709                 DEBUGADD(4,("Printer not found\n"));
710                 return WERR_INVALID_PRINTER_NAME;
711         }
712
713         if (cache_key != NULL) {
714                 gencache_set(cache_key, sname, time(NULL)+300);
715                 TALLOC_FREE(cache_key);
716         }
717
718         DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
719
720         strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
721
722         return WERR_OK;
723 }
724
725 /****************************************************************************
726  Find first available printer slot. creates a printer handle for you.
727  ****************************************************************************/
728
729 static WERROR open_printer_hnd(struct pipes_struct *p,
730                                struct policy_handle *hnd,
731                                const char *name,
732                                uint32_t access_granted)
733 {
734         struct printer_handle *new_printer;
735         WERROR result;
736
737         DEBUG(10,("open_printer_hnd: name [%s]\n", name));
738
739         new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
740         if (new_printer == NULL) {
741                 return WERR_NOMEM;
742         }
743         talloc_set_destructor(new_printer, printer_entry_destructor);
744
745         /* This also steals the printer_handle on the policy_handle */
746         if (!create_policy_hnd(p, hnd, new_printer)) {
747                 TALLOC_FREE(new_printer);
748                 return WERR_INVALID_HANDLE;
749         }
750
751         /* Add to the internal list. */
752         DLIST_ADD(printers_list, new_printer);
753
754         new_printer->notify.option=NULL;
755
756         if (!set_printer_hnd_printertype(new_printer, name)) {
757                 close_printer_handle(p, hnd);
758                 return WERR_INVALID_HANDLE;
759         }
760
761         result = set_printer_hnd_name(p->mem_ctx,
762                                       get_session_info_system(),
763                                       p->msg_ctx,
764                                       new_printer, name);
765         if (!W_ERROR_IS_OK(result)) {
766                 close_printer_handle(p, hnd);
767                 return result;
768         }
769
770         new_printer->access_granted = access_granted;
771
772         DEBUG(5, ("%d printer handles active\n",
773                   (int)num_pipe_handles(p)));
774
775         return WERR_OK;
776 }
777
778 /***************************************************************************
779  check to see if the client motify handle is monitoring the notification
780  given by (notify_type, notify_field).
781  **************************************************************************/
782
783 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
784                                       uint16_t notify_field)
785 {
786         return true;
787 }
788
789 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
790                                 uint16_t notify_field)
791 {
792         struct spoolss_NotifyOption *option = p->notify.option;
793         uint32_t i, j;
794
795         /*
796          * Flags should always be zero when the change notify
797          * is registered by the client's spooler.  A user Win32 app
798          * might use the flags though instead of the NOTIFY_OPTION_INFO
799          * --jerry
800          */
801
802         if (!option) {
803                 return false;
804         }
805
806         if (p->notify.flags)
807                 return is_monitoring_event_flags(
808                         p->notify.flags, notify_type, notify_field);
809
810         for (i = 0; i < option->count; i++) {
811
812                 /* Check match for notify_type */
813
814                 if (option->types[i].type != notify_type)
815                         continue;
816
817                 /* Check match for field */
818
819                 for (j = 0; j < option->types[i].count; j++) {
820                         if (option->types[i].fields[j].field == notify_field) {
821                                 return true;
822                         }
823                 }
824         }
825
826         DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
827                    p->servername, p->sharename, notify_type, notify_field));
828
829         return false;
830 }
831
832 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
833         _data->data.integer[0] = _integer; \
834         _data->data.integer[1] = 0;
835
836
837 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
838         _data->data.string.string = talloc_strdup(mem_ctx, _p); \
839         if (!_data->data.string.string) {\
840                 _data->data.string.size = 0; \
841         } \
842         _data->data.string.size = strlen_m_term(_p) * 2;
843
844 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
845         _data->data.devmode.devmode = _devmode;
846
847 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
848         _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
849         if (!_data->data.sd.sd) { \
850                 _data->data.sd.sd_size = 0; \
851         } \
852         _data->data.sd.sd_size = \
853                 ndr_size_security_descriptor(_data->data.sd.sd, 0);
854
855 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
856                                    struct tm *t,
857                                    const char **pp,
858                                    uint32_t *plen)
859 {
860         struct spoolss_Time st;
861         uint32_t len = 16;
862         char *p;
863
864         if (!init_systemtime(&st, t)) {
865                 return;
866         }
867
868         p = talloc_array(mem_ctx, char, len);
869         if (!p) {
870                 return;
871         }
872
873         /*
874          * Systemtime must be linearized as a set of UINT16's.
875          * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
876          */
877
878         SSVAL(p, 0, st.year);
879         SSVAL(p, 2, st.month);
880         SSVAL(p, 4, st.day_of_week);
881         SSVAL(p, 6, st.day);
882         SSVAL(p, 8, st.hour);
883         SSVAL(p, 10, st.minute);
884         SSVAL(p, 12, st.second);
885         SSVAL(p, 14, st.millisecond);
886
887         *pp = p;
888         *plen = len;
889 }
890
891 /* Convert a notification message to a struct spoolss_Notify */
892
893 static void notify_one_value(struct spoolss_notify_msg *msg,
894                              struct spoolss_Notify *data,
895                              TALLOC_CTX *mem_ctx)
896 {
897         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
898 }
899
900 static void notify_string(struct spoolss_notify_msg *msg,
901                           struct spoolss_Notify *data,
902                           TALLOC_CTX *mem_ctx)
903 {
904         /* The length of the message includes the trailing \0 */
905
906         data->data.string.size = msg->len * 2;
907         data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
908         if (!data->data.string.string) {
909                 data->data.string.size = 0;
910                 return;
911         }
912 }
913
914 static void notify_system_time(struct spoolss_notify_msg *msg,
915                                struct spoolss_Notify *data,
916                                TALLOC_CTX *mem_ctx)
917 {
918         data->data.string.string = NULL;
919         data->data.string.size = 0;
920
921         if (msg->len != sizeof(time_t)) {
922                 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
923                           msg->len));
924                 return;
925         }
926
927         init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
928                                &data->data.string.string,
929                                &data->data.string.size);
930 }
931
932 struct notify2_message_table {
933         const char *name;
934         void (*fn)(struct spoolss_notify_msg *msg,
935                    struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
936 };
937
938 static struct notify2_message_table printer_notify_table[] = {
939         /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
940         /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
941         /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
942         /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
943         /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
944         /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
945         /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
946         /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
947         /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
948         /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
949         /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
950         /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
951         /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
952         /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
953         /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
954         /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
955         /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
956         /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
957         /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
958 };
959
960 static struct notify2_message_table job_notify_table[] = {
961         /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
962         /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
963         /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
964         /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
965         /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
966         /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
967         /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
968         /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
969         /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
970         /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
971         /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
972         /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
973         /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
974         /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
975         /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
976         /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
977         /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
978         /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
979         /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
980         /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
981         /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
982         /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
983         /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
984         /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
985 };
986
987
988 /***********************************************************************
989  Allocate talloc context for container object
990  **********************************************************************/
991
992 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
993 {
994         if ( !ctr )
995                 return;
996
997         ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
998
999         return;
1000 }
1001
1002 /***********************************************************************
1003  release all allocated memory and zero out structure
1004  **********************************************************************/
1005
1006 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1007 {
1008         if ( !ctr )
1009                 return;
1010
1011         if ( ctr->ctx )
1012                 talloc_destroy(ctr->ctx);
1013
1014         ZERO_STRUCTP(ctr);
1015
1016         return;
1017 }
1018
1019 /***********************************************************************
1020  **********************************************************************/
1021
1022 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1023 {
1024         if ( !ctr )
1025                 return NULL;
1026
1027         return ctr->ctx;
1028 }
1029
1030 /***********************************************************************
1031  **********************************************************************/
1032
1033 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1034 {
1035         if ( !ctr || !ctr->msg_groups )
1036                 return NULL;
1037
1038         if ( idx >= ctr->num_groups )
1039                 return NULL;
1040
1041         return &ctr->msg_groups[idx];
1042
1043 }
1044
1045 /***********************************************************************
1046  How many groups of change messages do we have ?
1047  **********************************************************************/
1048
1049 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1050 {
1051         if ( !ctr )
1052                 return 0;
1053
1054         return ctr->num_groups;
1055 }
1056
1057 /***********************************************************************
1058  Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1059  **********************************************************************/
1060
1061 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1062 {
1063         SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
1064         SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
1065         SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
1066         int                             i, new_slot;
1067
1068         if ( !ctr || !msg )
1069                 return 0;
1070
1071         /* loop over all groups looking for a matching printer name */
1072
1073         for ( i=0; i<ctr->num_groups; i++ ) {
1074                 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1075                         break;
1076         }
1077
1078         /* add a new group? */
1079
1080         if ( i == ctr->num_groups ) {
1081                 ctr->num_groups++;
1082
1083                 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1084                         DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1085                         return 0;
1086                 }
1087                 ctr->msg_groups = groups;
1088
1089                 /* clear the new entry and set the printer name */
1090
1091                 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1092                 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1093         }
1094
1095         /* add the change messages; 'i' is the correct index now regardless */
1096
1097         msg_grp = &ctr->msg_groups[i];
1098
1099         msg_grp->num_msgs++;
1100
1101         if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1102                 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1103                 return 0;
1104         }
1105         msg_grp->msgs = msg_list;
1106
1107         new_slot = msg_grp->num_msgs-1;
1108         memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1109
1110         /* need to allocate own copy of data */
1111
1112         if ( msg->len != 0 )
1113                 msg_grp->msgs[new_slot].notify.data = (char *)
1114                         talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1115
1116         return ctr->num_groups;
1117 }
1118
1119 static void construct_info_data(struct spoolss_Notify *info_data,
1120                                 enum spoolss_NotifyType type,
1121                                 uint16_t field, int id);
1122
1123 /***********************************************************************
1124  Send a change notication message on all handles which have a call
1125  back registered
1126  **********************************************************************/
1127
1128 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1129                                   struct printer_handle *prn_hnd,
1130                                   SPOOLSS_NOTIFY_MSG *messages,
1131                                   uint32_t num_msgs,
1132                                   struct spoolss_Notify **_notifies,
1133                                   int *_count)
1134 {
1135         struct spoolss_Notify *notifies;
1136         SPOOLSS_NOTIFY_MSG *msg;
1137         int count = 0;
1138         uint32_t id;
1139         int i;
1140
1141         notifies = talloc_zero_array(mem_ctx,
1142                                      struct spoolss_Notify, num_msgs);
1143         if (!notifies) {
1144                 return ENOMEM;
1145         }
1146
1147         for (i = 0; i < num_msgs; i++) {
1148
1149                 msg = &messages[i];
1150
1151                 /* Are we monitoring this event? */
1152
1153                 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1154                         continue;
1155                 }
1156
1157                 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1158                            "for printer [%s]\n",
1159                            msg->type, msg->field, prn_hnd->sharename));
1160
1161                 /*
1162                  * if the is a printer notification handle and not a job
1163                  * notification type, then set the id to 0.
1164                  * Otherwise just use what was specified in the message.
1165                  *
1166                  * When registering change notification on a print server
1167                  * handle we always need to send back the id (snum) matching
1168                  * the printer for which the change took place.
1169                  * For change notify registered on a printer handle,
1170                  * this does not matter and the id should be 0.
1171                  *
1172                  * --jerry
1173                  */
1174
1175                 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1176                     (prn_hnd->printer_type == SPLHND_PRINTER)) {
1177                         id = 0;
1178                 } else {
1179                         id = msg->id;
1180                 }
1181
1182                 /* Convert unix jobid to smb jobid */
1183
1184                 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1185                         id = sysjob_to_jobid(msg->id);
1186
1187                         if (id == -1) {
1188                                 DEBUG(3, ("no such unix jobid %d\n",
1189                                           msg->id));
1190                                 continue;
1191                         }
1192                 }
1193
1194                 construct_info_data(&notifies[count],
1195                                     msg->type, msg->field, id);
1196
1197                 switch(msg->type) {
1198                 case PRINTER_NOTIFY_TYPE:
1199                         if (printer_notify_table[msg->field].fn) {
1200                                 printer_notify_table[msg->field].fn(msg,
1201                                                 &notifies[count], mem_ctx);
1202                         }
1203                         break;
1204
1205                 case JOB_NOTIFY_TYPE:
1206                         if (job_notify_table[msg->field].fn) {
1207                                 job_notify_table[msg->field].fn(msg,
1208                                                 &notifies[count], mem_ctx);
1209                         }
1210                         break;
1211
1212                 default:
1213                         DEBUG(5, ("Unknown notification type %d\n",
1214                                   msg->type));
1215                         continue;
1216                 }
1217
1218                 count++;
1219         }
1220
1221         *_notifies = notifies;
1222         *_count = count;
1223
1224         return 0;
1225 }
1226
1227 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1228                                 struct printer_handle *prn_hnd,
1229                                 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1230 {
1231         struct spoolss_Notify *notifies;
1232         int count = 0;
1233         union spoolss_ReplyPrinterInfo info;
1234         struct spoolss_NotifyInfo info0;
1235         uint32_t reply_result;
1236         NTSTATUS status;
1237         WERROR werr;
1238         int ret;
1239
1240         /* Is there notification on this handle? */
1241         if (prn_hnd->notify.cli_chan == NULL ||
1242             prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1243             prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1244             prn_hnd->notify.cli_chan->active_connections == 0) {
1245                 return 0;
1246         }
1247
1248         DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1249                    prn_hnd->servername, prn_hnd->sharename));
1250
1251         /* For this printer? Print servers always receive notifications. */
1252         if ((prn_hnd->printer_type == SPLHND_PRINTER)  &&
1253             (!strequal(msg_group->printername, prn_hnd->sharename))) {
1254                 return 0;
1255         }
1256
1257         DEBUG(10,("Our printer\n"));
1258
1259         /* build the array of change notifications */
1260         ret = build_notify2_messages(mem_ctx, prn_hnd,
1261                                      msg_group->msgs,
1262                                      msg_group->num_msgs,
1263                                      &notifies, &count);
1264         if (ret) {
1265                 return ret;
1266         }
1267
1268         info0.version   = 0x2;
1269         info0.flags     = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1270         info0.count     = count;
1271         info0.notifies  = notifies;
1272
1273         info.info0 = &info0;
1274
1275         status = dcerpc_spoolss_RouterReplyPrinterEx(
1276                                 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1277                                 mem_ctx,
1278                                 &prn_hnd->notify.cli_hnd,
1279                                 prn_hnd->notify.change, /* color */
1280                                 prn_hnd->notify.flags,
1281                                 &reply_result,
1282                                 0, /* reply_type, must be 0 */
1283                                 info, &werr);
1284         if (!NT_STATUS_IS_OK(status)) {
1285                 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1286                           "failed: %s\n",
1287                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1288                           nt_errstr(status)));
1289                 werr = ntstatus_to_werror(status);
1290         } else if (!W_ERROR_IS_OK(werr)) {
1291                 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1292                           "failed: %s\n",
1293                           prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1294                           win_errstr(werr)));
1295         }
1296         switch (reply_result) {
1297         case 0:
1298                 break;
1299         case PRINTER_NOTIFY_INFO_DISCARDED:
1300         case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1301         case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1302                 break;
1303         default:
1304                 break;
1305         }
1306
1307         return 0;
1308 }
1309
1310 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1311 {
1312         struct printer_handle    *p;
1313         TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
1314         SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1315         int ret;
1316
1317         if ( !msg_group ) {
1318                 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1319                 return;
1320         }
1321
1322         if (!msg_group->msgs) {
1323                 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1324                 return;
1325         }
1326
1327         DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1328
1329         /* loop over all printers */
1330
1331         for (p = printers_list; p; p = p->next) {
1332                 ret = send_notify2_printer(mem_ctx, p, msg_group);
1333                 if (ret) {
1334                         goto done;
1335                 }
1336         }
1337
1338 done:
1339         DEBUG(8,("send_notify2_changes: Exit...\n"));
1340         return;
1341 }
1342
1343 /***********************************************************************
1344  **********************************************************************/
1345
1346 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1347 {
1348
1349         uint32_t tv_sec, tv_usec;
1350         size_t offset = 0;
1351
1352         /* Unpack message */
1353
1354         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1355                              msg->printer);
1356
1357         offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1358                                 &tv_sec, &tv_usec,
1359                                 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1360
1361         if (msg->len == 0)
1362                 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1363                            &msg->notify.value[0], &msg->notify.value[1]);
1364         else
1365                 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1366                            &msg->len, &msg->notify.data);
1367
1368         DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1369                   msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1370
1371         tv->tv_sec = tv_sec;
1372         tv->tv_usec = tv_usec;
1373
1374         if (msg->len == 0)
1375                 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1376                           msg->notify.value[1]));
1377         else
1378                 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1379
1380         return true;
1381 }
1382
1383 /********************************************************************
1384  Receive a notify2 message list
1385  ********************************************************************/
1386
1387 static void receive_notify2_message_list(struct messaging_context *msg,
1388                                          void *private_data,
1389                                          uint32_t msg_type,
1390                                          struct server_id server_id,
1391                                          DATA_BLOB *data)
1392 {
1393         size_t                  msg_count, i;
1394         char                    *buf = (char *)data->data;
1395         char                    *msg_ptr;
1396         size_t                  msg_len;
1397         SPOOLSS_NOTIFY_MSG      notify;
1398         SPOOLSS_NOTIFY_MSG_CTR  messages;
1399         int                     num_groups;
1400
1401         if (data->length < 4) {
1402                 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1403                 return;
1404         }
1405
1406         msg_count = IVAL(buf, 0);
1407         msg_ptr = buf + 4;
1408
1409         DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1410
1411         if (msg_count == 0) {
1412                 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1413                 return;
1414         }
1415
1416         /* initialize the container */
1417
1418         ZERO_STRUCT( messages );
1419         notify_msg_ctr_init( &messages );
1420
1421         /*
1422          * build message groups for each printer identified
1423          * in a change_notify msg.  Remember that a PCN message
1424          * includes the handle returned for the srv_spoolss_replyopenprinter()
1425          * call.  Therefore messages are grouped according to printer handle.
1426          */
1427
1428         for ( i=0; i<msg_count; i++ ) {
1429                 struct timeval msg_tv;
1430
1431                 if (msg_ptr + 4 - buf > data->length) {
1432                         DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1433                         return;
1434                 }
1435
1436                 msg_len = IVAL(msg_ptr,0);
1437                 msg_ptr += 4;
1438
1439                 if (msg_ptr + msg_len - buf > data->length) {
1440                         DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1441                         return;
1442                 }
1443
1444                 /* unpack messages */
1445
1446                 ZERO_STRUCT( notify );
1447                 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1448                 msg_ptr += msg_len;
1449
1450                 /* add to correct list in container */
1451
1452                 notify_msg_ctr_addmsg( &messages, &notify );
1453
1454                 /* free memory that might have been allocated by notify2_unpack_msg() */
1455
1456                 if ( notify.len != 0 )
1457                         SAFE_FREE( notify.notify.data );
1458         }
1459
1460         /* process each group of messages */
1461
1462         num_groups = notify_msg_ctr_numgroups( &messages );
1463         for ( i=0; i<num_groups; i++ )
1464                 send_notify2_changes( &messages, i );
1465
1466
1467         /* cleanup */
1468
1469         DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1470                 (uint32_t)msg_count ));
1471
1472         notify_msg_ctr_destroy( &messages );
1473
1474         return;
1475 }
1476
1477 /********************************************************************
1478  Send a message to ourself about new driver being installed
1479  so we can upgrade the information for each printer bound to this
1480  driver
1481  ********************************************************************/
1482
1483 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1484                                             struct messaging_context *msg_ctx)
1485 {
1486         int len = strlen(drivername);
1487
1488         if (!len)
1489                 return false;
1490
1491         DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1492                 drivername));
1493
1494         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1495                            MSG_PRINTER_DRVUPGRADE,
1496                            (const uint8_t *)drivername, len+1);
1497
1498         return true;
1499 }
1500
1501 void srv_spoolss_cleanup(void)
1502 {
1503         struct printer_session_counter *session_counter;
1504
1505         for (session_counter = counter_list;
1506              session_counter != NULL;
1507              session_counter = counter_list) {
1508                 DLIST_REMOVE(counter_list, session_counter);
1509                 TALLOC_FREE(session_counter);
1510         }
1511 }
1512
1513 /**********************************************************************
1514  callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1515  over all printers, upgrading ones as necessary
1516  **********************************************************************/
1517
1518 void do_drv_upgrade_printer(struct messaging_context *msg,
1519                             void *private_data,
1520                             uint32_t msg_type,
1521                             struct server_id server_id,
1522                             DATA_BLOB *data)
1523 {
1524         TALLOC_CTX *tmp_ctx;
1525         const struct auth_session_info *session_info = get_session_info_system();
1526         struct spoolss_PrinterInfo2 *pinfo2;
1527         WERROR result;
1528         const char *drivername;
1529         int snum;
1530         int n_services = lp_numservices();
1531         struct dcerpc_binding_handle *b = NULL;
1532
1533         tmp_ctx = talloc_new(NULL);
1534         if (!tmp_ctx) return;
1535
1536         drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1537         if (!drivername) {
1538                 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1539                 goto done;
1540         }
1541
1542         DEBUG(10, ("do_drv_upgrade_printer: "
1543                    "Got message for new driver [%s]\n", drivername));
1544
1545         /* Iterate the printer list */
1546
1547         for (snum = 0; snum < n_services; snum++) {
1548                 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1549                         continue;
1550                 }
1551
1552                 /* ignore [printers] share */
1553                 if (strequal(lp_const_servicename(snum), "printers")) {
1554                         continue;
1555                 }
1556
1557                 if (b == NULL) {
1558                         result = winreg_printer_binding_handle(tmp_ctx,
1559                                                                session_info,
1560                                                                msg,
1561                                                                &b);
1562                         if (!W_ERROR_IS_OK(result)) {
1563                                 break;
1564                         }
1565                 }
1566
1567                 result = winreg_get_printer(tmp_ctx, b,
1568                                             lp_const_servicename(snum),
1569                                             &pinfo2);
1570
1571                 if (!W_ERROR_IS_OK(result)) {
1572                         continue;
1573                 }
1574
1575                 if (!pinfo2->drivername) {
1576                         continue;
1577                 }
1578
1579                 if (strcmp(drivername, pinfo2->drivername) != 0) {
1580                         continue;
1581                 }
1582
1583                 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1584
1585                 /* all we care about currently is the change_id */
1586                 result = winreg_printer_update_changeid(tmp_ctx, b,
1587                                                         pinfo2->printername);
1588
1589                 if (!W_ERROR_IS_OK(result)) {
1590                         DEBUG(3, ("do_drv_upgrade_printer: "
1591                                   "Failed to update changeid [%s]\n",
1592                                   win_errstr(result)));
1593                 }
1594         }
1595
1596         /* all done */
1597 done:
1598         talloc_free(tmp_ctx);
1599 }
1600
1601 /********************************************************************
1602  Update the cache for all printq's with a registered client
1603  connection
1604  ********************************************************************/
1605
1606 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1607 {
1608         struct printer_handle *printer = printers_list;
1609         int snum;
1610
1611         /* loop through all printers and update the cache where
1612            a client is connected */
1613         while (printer) {
1614                 if ((printer->printer_type == SPLHND_PRINTER) &&
1615                     ((printer->notify.cli_chan != NULL) &&
1616                      (printer->notify.cli_chan->active_connections > 0))) {
1617                         snum = print_queue_snum(printer->sharename);
1618                         print_queue_status(msg_ctx, snum, NULL, NULL);
1619                 }
1620
1621                 printer = printer->next;
1622         }
1623
1624         return;
1625 }
1626
1627 /****************************************************************
1628  _spoolss_OpenPrinter
1629 ****************************************************************/
1630
1631 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1632                             struct spoolss_OpenPrinter *r)
1633 {
1634         struct spoolss_OpenPrinterEx e;
1635         struct spoolss_UserLevel1 level1;
1636         WERROR werr;
1637
1638         ZERO_STRUCT(level1);
1639
1640         e.in.printername        = r->in.printername;
1641         e.in.datatype           = r->in.datatype;
1642         e.in.devmode_ctr        = r->in.devmode_ctr;
1643         e.in.access_mask        = r->in.access_mask;
1644         e.in.userlevel_ctr.level                = 1;
1645         e.in.userlevel_ctr.user_info.level1     = &level1;
1646
1647         e.out.handle            = r->out.handle;
1648
1649         werr = _spoolss_OpenPrinterEx(p, &e);
1650
1651         if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1652                 /* OpenPrinterEx returns this for a bad
1653                  * printer name. We must return WERR_INVALID_PRINTER_NAME
1654                  * instead.
1655                  */
1656                 werr = WERR_INVALID_PRINTER_NAME;
1657         }
1658
1659         return werr;
1660 }
1661
1662 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1663                               struct spoolss_DeviceMode *orig,
1664                               struct spoolss_DeviceMode **dest)
1665 {
1666         struct spoolss_DeviceMode *dm;
1667
1668         dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1669         if (!dm) {
1670                 return WERR_NOMEM;
1671         }
1672
1673         /* copy all values, then duplicate strings and structs */
1674         *dm = *orig;
1675
1676         dm->devicename = talloc_strdup(dm, orig->devicename);
1677         if (!dm->devicename) {
1678                 return WERR_NOMEM;
1679         }
1680         dm->formname = talloc_strdup(dm, orig->formname);
1681         if (!dm->formname) {
1682                 return WERR_NOMEM;
1683         }
1684         if (orig->driverextra_data.data) {
1685                 dm->driverextra_data.data =
1686                         (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1687                                         orig->driverextra_data.length);
1688                 if (!dm->driverextra_data.data) {
1689                         return WERR_NOMEM;
1690                 }
1691         }
1692
1693         *dest = dm;
1694         return WERR_OK;
1695 }
1696
1697 /****************************************************************
1698  _spoolss_OpenPrinterEx
1699 ****************************************************************/
1700
1701 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1702                               struct spoolss_OpenPrinterEx *r)
1703 {
1704         int snum;
1705         char *raddr;
1706         char *rhost;
1707         struct printer_handle *Printer=NULL;
1708         WERROR result;
1709         int rc;
1710
1711         if (!r->in.printername) {
1712                 return WERR_INVALID_PARAM;
1713         }
1714
1715         if (!*r->in.printername) {
1716                 return WERR_INVALID_PARAM;
1717         }
1718
1719         if (r->in.userlevel_ctr.level > 3) {
1720                 return WERR_INVALID_PARAM;
1721         }
1722         if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1723             (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1724             (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1725                 return WERR_INVALID_PARAM;
1726         }
1727
1728         /* some sanity check because you can open a printer or a print server */
1729         /* aka: \\server\printer or \\server */
1730
1731         DEBUGADD(3,("checking name: %s\n", r->in.printername));
1732
1733         result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1734         if (!W_ERROR_IS_OK(result)) {
1735                 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1736                         "for printer %s\n", r->in.printername));
1737                 ZERO_STRUCTP(r->out.handle);
1738                 return result;
1739         }
1740
1741         Printer = find_printer_index_by_hnd(p, r->out.handle);
1742         if ( !Printer ) {
1743                 DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
1744                         "handle we created for printer %s\n", r->in.printername));
1745                 close_printer_handle(p, r->out.handle);
1746                 ZERO_STRUCTP(r->out.handle);
1747                 return WERR_INVALID_PARAM;
1748         }
1749
1750         /*
1751          * First case: the user is opening the print server:
1752          *
1753          * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1754          * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1755          *
1756          * Then both Win2k and WinNT clients try an OpenPrinterEx with
1757          * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1758          * or if the user is listed in the smb.conf printer admin parameter.
1759          *
1760          * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1761          * client view printer folder, but does not show the MSAPW.
1762          *
1763          * Note: this test needs code to check access rights here too. Jeremy
1764          * could you look at this?
1765          *
1766          * Second case: the user is opening a printer:
1767          * NT doesn't let us connect to a printer if the connecting user
1768          * doesn't have print permission.
1769          *
1770          * Third case: user is opening a Port Monitor
1771          * access checks same as opening a handle to the print server.
1772          */
1773
1774         switch (Printer->printer_type )
1775         {
1776         case SPLHND_SERVER:
1777         case SPLHND_PORTMON_TCP:
1778         case SPLHND_PORTMON_LOCAL:
1779                 /* Printserver handles use global struct... */
1780
1781                 snum = -1;
1782
1783                 /* Map standard access rights to object specific access rights */
1784
1785                 se_map_standard(&r->in.access_mask,
1786                                 &printserver_std_mapping);
1787
1788                 /* Deny any object specific bits that don't apply to print
1789                    servers (i.e printer and job specific bits) */
1790
1791                 r->in.access_mask &= SEC_MASK_SPECIFIC;
1792
1793                 if (r->in.access_mask &
1794                     ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1795                         DEBUG(3, ("access DENIED for non-printserver bits\n"));
1796                         close_printer_handle(p, r->out.handle);
1797                         ZERO_STRUCTP(r->out.handle);
1798                         return WERR_ACCESS_DENIED;
1799                 }
1800
1801                 /* Allow admin access */
1802
1803                 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1804                 {
1805                         if (!lp_ms_add_printer_wizard()) {
1806                                 close_printer_handle(p, r->out.handle);
1807                                 ZERO_STRUCTP(r->out.handle);
1808                                 return WERR_ACCESS_DENIED;
1809                         }
1810
1811                         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1812                            and not a printer admin, then fail */
1813
1814                         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1815                             !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1816                             !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1817                                                 p->session_info->security_token)) {
1818                                 close_printer_handle(p, r->out.handle);
1819                                 ZERO_STRUCTP(r->out.handle);
1820                                 DEBUG(3,("access DENIED as user is not root, "
1821                                         "has no printoperator privilege, "
1822                                         "not a member of the printoperator builtin group and "
1823                                         "is not in printer admin list"));
1824                                 return WERR_ACCESS_DENIED;
1825                         }
1826
1827                         r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1828                 }
1829                 else
1830                 {
1831                         r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1832                 }
1833
1834                 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1835                         ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1836
1837                 /* We fall through to return WERR_OK */
1838                 break;
1839
1840         case SPLHND_PRINTER:
1841                 /* NT doesn't let us connect to a printer if the connecting user
1842                    doesn't have print permission.  */
1843
1844                 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1845                         close_printer_handle(p, r->out.handle);
1846                         ZERO_STRUCTP(r->out.handle);
1847                         return WERR_BADFID;
1848                 }
1849
1850                 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1851                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1852                 }
1853
1854                 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1855
1856                 /* map an empty access mask to the minimum access mask */
1857                 if (r->in.access_mask == 0x0)
1858                         r->in.access_mask = PRINTER_ACCESS_USE;
1859
1860                 /*
1861                  * If we are not serving the printer driver for this printer,
1862                  * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE.  This
1863                  * will keep NT clients happy  --jerry
1864                  */
1865
1866                 if (lp_use_client_driver(snum)
1867                         && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1868                 {
1869                         r->in.access_mask = PRINTER_ACCESS_USE;
1870                 }
1871
1872                 /* check smb.conf parameters and the the sec_desc */
1873                 raddr = tsocket_address_inet_addr_string(p->remote_address,
1874                                                          p->mem_ctx);
1875                 if (raddr == NULL) {
1876                         return WERR_NOMEM;
1877                 }
1878
1879                 rc = get_remote_hostname(p->remote_address,
1880                                          &rhost,
1881                                          p->mem_ctx);
1882                 if (rc < 0) {
1883                         return WERR_NOMEM;
1884                 }
1885                 if (strequal(rhost, "UNKNOWN")) {
1886                         rhost = raddr;
1887                 }
1888
1889                 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1890                                   rhost, raddr)) {
1891                         DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1892                         ZERO_STRUCTP(r->out.handle);
1893                         return WERR_ACCESS_DENIED;
1894                 }
1895
1896                 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1897                                    p->session_info->security_token, snum) ||
1898                     !print_access_check(p->session_info,
1899                                         p->msg_ctx,
1900                                         snum,
1901                                         r->in.access_mask)) {
1902                         DEBUG(3, ("access DENIED for printer open\n"));
1903                         close_printer_handle(p, r->out.handle);
1904                         ZERO_STRUCTP(r->out.handle);
1905                         return WERR_ACCESS_DENIED;
1906                 }
1907
1908                 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1909                         DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1910                         close_printer_handle(p, r->out.handle);
1911                         ZERO_STRUCTP(r->out.handle);
1912                         return WERR_ACCESS_DENIED;
1913                 }
1914
1915                 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1916                         r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1917                 else
1918                         r->in.access_mask = PRINTER_ACCESS_USE;
1919
1920                 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1921                         ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1922
1923                 winreg_create_printer_internal(p->mem_ctx,
1924                                       get_session_info_system(),
1925                                       p->msg_ctx,
1926                                       lp_const_servicename(snum));
1927
1928                 break;
1929
1930         default:
1931                 /* sanity check to prevent programmer error */
1932                 ZERO_STRUCTP(r->out.handle);
1933                 return WERR_BADFID;
1934         }
1935
1936         Printer->access_granted = r->in.access_mask;
1937
1938         /*
1939          * If the client sent a devmode in the OpenPrinter() call, then
1940          * save it here in case we get a job submission on this handle
1941          */
1942
1943          if ((Printer->printer_type != SPLHND_SERVER)
1944           && (r->in.devmode_ctr.devmode != NULL)) {
1945                 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1946                                 &Printer->devmode);
1947          }
1948
1949         return WERR_OK;
1950 }
1951
1952 /****************************************************************
1953  _spoolss_ClosePrinter
1954 ****************************************************************/
1955
1956 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1957                              struct spoolss_ClosePrinter *r)
1958 {
1959         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1960
1961         if (Printer && Printer->document_started) {
1962                 struct spoolss_EndDocPrinter e;
1963
1964                 e.in.handle = r->in.handle;
1965
1966                 _spoolss_EndDocPrinter(p, &e);
1967         }
1968
1969         if (!close_printer_handle(p, r->in.handle))
1970                 return WERR_BADFID;
1971
1972         /* clear the returned printer handle.  Observed behavior
1973            from Win2k server.  Don't think this really matters.
1974            Previous code just copied the value of the closed
1975            handle.    --jerry */
1976
1977         ZERO_STRUCTP(r->out.handle);
1978
1979         return WERR_OK;
1980 }
1981
1982 /****************************************************************
1983  _spoolss_DeletePrinter
1984 ****************************************************************/
1985
1986 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1987                               struct spoolss_DeletePrinter *r)
1988 {
1989         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1990         WERROR result;
1991         int snum;
1992
1993         if (Printer && Printer->document_started) {
1994                 struct spoolss_EndDocPrinter e;
1995
1996                 e.in.handle = r->in.handle;
1997
1998                 _spoolss_EndDocPrinter(p, &e);
1999         }
2000
2001         if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2002                 winreg_delete_printer_key_internal(p->mem_ctx,
2003                                           get_session_info_system(),
2004                                           p->msg_ctx,
2005                                           lp_const_servicename(snum),
2006                                           "");
2007         }
2008
2009         result = delete_printer_handle(p, r->in.handle);
2010
2011         return result;
2012 }
2013
2014 /*******************************************************************
2015  * static function to lookup the version id corresponding to an
2016  * long architecture string
2017  ******************************************************************/
2018
2019 static const struct print_architecture_table_node archi_table[]= {
2020
2021         {"Windows 4.0",          SPL_ARCH_WIN40,        0 },
2022         {"Windows NT x86",       SPL_ARCH_W32X86,       2 },
2023         {"Windows NT R4000",     SPL_ARCH_W32MIPS,      2 },
2024         {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA,     2 },
2025         {"Windows NT PowerPC",   SPL_ARCH_W32PPC,       2 },
2026         {"Windows IA64",         SPL_ARCH_IA64,         3 },
2027         {"Windows x64",          SPL_ARCH_X64,          3 },
2028         {NULL,                   "",            -1 }
2029 };
2030
2031 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2032                                    SPOOLSS_DRIVER_VERSION_NT35,
2033                                    SPOOLSS_DRIVER_VERSION_NT4,
2034                                    SPOOLSS_DRIVER_VERSION_200X,
2035                                    -1};
2036
2037 static int get_version_id(const char *arch)
2038 {
2039         int i;
2040
2041         for (i=0; archi_table[i].long_archi != NULL; i++)
2042         {
2043                 if (strcmp(arch, archi_table[i].long_archi) == 0)
2044                         return (archi_table[i].version);
2045         }
2046
2047         return -1;
2048 }
2049
2050 /****************************************************************
2051  _spoolss_DeletePrinterDriver
2052 ****************************************************************/
2053
2054 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2055                                     struct spoolss_DeletePrinterDriver *r)
2056 {
2057
2058         struct spoolss_DriverInfo8 *info = NULL;
2059         int                             version;
2060         WERROR                          status;
2061         struct dcerpc_binding_handle *b;
2062         TALLOC_CTX *tmp_ctx = NULL;
2063         int i;
2064         bool found;
2065
2066         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2067            and not a printer admin, then fail */
2068
2069         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2070             !security_token_has_privilege(p->session_info->security_token,
2071                                           SEC_PRIV_PRINT_OPERATOR)) {
2072                 return WERR_ACCESS_DENIED;
2073         }
2074
2075         /* check that we have a valid driver name first */
2076
2077         if ((version = get_version_id(r->in.architecture)) == -1) {
2078                 return WERR_INVALID_ENVIRONMENT;
2079         }
2080
2081         tmp_ctx = talloc_new(p->mem_ctx);
2082         if (!tmp_ctx) {
2083                 return WERR_NOMEM;
2084         }
2085
2086         status = winreg_printer_binding_handle(tmp_ctx,
2087                                                get_session_info_system(),
2088                                                p->msg_ctx,
2089                                                &b);
2090         if (!W_ERROR_IS_OK(status)) {
2091                 goto done;
2092         }
2093
2094         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2095                 status = winreg_get_driver(tmp_ctx, b,
2096                                            r->in.architecture, r->in.driver,
2097                                            drv_cversion[i], &info);
2098                 if (!W_ERROR_IS_OK(status)) {
2099                         DEBUG(5, ("skipping del of driver with version %d\n",
2100                                   drv_cversion[i]));
2101                         continue;
2102                 }
2103                 found = true;
2104
2105                 if (printer_driver_in_use(tmp_ctx, b, info)) {
2106                         status = WERR_PRINTER_DRIVER_IN_USE;
2107                         goto done;
2108                 }
2109
2110                 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2111                 if (!W_ERROR_IS_OK(status)) {
2112                         DEBUG(0, ("failed del of driver with version %d\n",
2113                                   drv_cversion[i]));
2114                         goto done;
2115                 }
2116         }
2117         if (found == false) {
2118                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2119                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2120         } else {
2121                 status = WERR_OK;
2122         }
2123
2124 done:
2125         talloc_free(tmp_ctx);
2126
2127         return status;
2128 }
2129
2130 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2131                                   struct pipes_struct *p,
2132                                   struct spoolss_DeletePrinterDriverEx *r,
2133                                   struct dcerpc_binding_handle *b,
2134                                   struct spoolss_DriverInfo8 *info)
2135 {
2136         WERROR status;
2137         bool delete_files;
2138
2139         if (printer_driver_in_use(mem_ctx, b, info)) {
2140                 status = WERR_PRINTER_DRIVER_IN_USE;
2141                 goto done;
2142         }
2143
2144         /*
2145          * we have a couple of cases to consider.
2146          * (1) Are any files in use?  If so and DPD_DELETE_ALL_FILES is set,
2147          *     then the delete should fail if **any** files overlap with
2148          *     other drivers
2149          * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2150          *     non-overlapping files
2151          * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2152          *     are set, then do not delete any files
2153          * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2154          */
2155
2156         delete_files = r->in.delete_flags
2157                         & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2158
2159
2160         if (delete_files) {
2161                 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2162                 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2163                         status = WERR_PRINTER_DRIVER_IN_USE;
2164                         goto done;
2165                 }
2166                 /*
2167                  * printer_driver_files_in_use() has trimmed overlapping files
2168                  * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2169                  */
2170         }
2171
2172
2173         status = winreg_del_driver(mem_ctx, b, info, info->version);
2174         if (!W_ERROR_IS_OK(status)) {
2175                 goto done;
2176         }
2177
2178         /*
2179          * now delete any associated files if delete_files is
2180          * true. Even if this part failes, we return succes
2181          * because the driver doesn not exist any more
2182          */
2183         if (delete_files) {
2184                 delete_driver_files(p->session_info, info);
2185         }
2186
2187 done:
2188         return status;
2189 }
2190
2191 /****************************************************************
2192  _spoolss_DeletePrinterDriverEx
2193 ****************************************************************/
2194
2195 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2196                                       struct spoolss_DeletePrinterDriverEx *r)
2197 {
2198         struct spoolss_DriverInfo8 *info = NULL;
2199         WERROR                          status;
2200         struct dcerpc_binding_handle *b;
2201         TALLOC_CTX *tmp_ctx = NULL;
2202         int i;
2203         bool found;
2204
2205         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2206            and not a printer admin, then fail */
2207
2208         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2209             !security_token_has_privilege(p->session_info->security_token,
2210                                           SEC_PRIV_PRINT_OPERATOR)) {
2211                 return WERR_ACCESS_DENIED;
2212         }
2213
2214         /* check that we have a valid driver name first */
2215         if (get_version_id(r->in.architecture) == -1) {
2216                 /* this is what NT returns */
2217                 return WERR_INVALID_ENVIRONMENT;
2218         }
2219
2220         tmp_ctx = talloc_new(p->mem_ctx);
2221         if (!tmp_ctx) {
2222                 return WERR_NOMEM;
2223         }
2224
2225         status = winreg_printer_binding_handle(tmp_ctx,
2226                                                get_session_info_system(),
2227                                                p->msg_ctx,
2228                                                &b);
2229         if (!W_ERROR_IS_OK(status)) {
2230                 goto done;
2231         }
2232
2233         for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2234                 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2235                  && (drv_cversion[i] != r->in.version)) {
2236                         continue;
2237                 }
2238
2239                 /* check if a driver with this version exists before delete */
2240                 status = winreg_get_driver(tmp_ctx, b,
2241                                            r->in.architecture, r->in.driver,
2242                                            drv_cversion[i], &info);
2243                 if (!W_ERROR_IS_OK(status)) {
2244                         DEBUG(5, ("skipping del of driver with version %d\n",
2245                                   drv_cversion[i]));
2246                         continue;
2247                 }
2248                 found = true;
2249
2250                 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2251                 if (!W_ERROR_IS_OK(status)) {
2252                         DEBUG(0, ("failed to delete driver with version %d\n",
2253                                   drv_cversion[i]));
2254                         goto done;
2255                 }
2256         }
2257         if (found == false) {
2258                 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2259                 status = WERR_UNKNOWN_PRINTER_DRIVER;
2260         } else {
2261                 status = WERR_OK;
2262         }
2263
2264 done:
2265         talloc_free(tmp_ctx);
2266         return status;
2267 }
2268
2269
2270 /********************************************************************
2271  GetPrinterData on a printer server Handle.
2272 ********************************************************************/
2273
2274 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2275                                             const char *value,
2276                                             enum winreg_Type *type,
2277                                             union spoolss_PrinterData *data)
2278 {
2279         DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2280
2281         if (!strcasecmp_m(value, "W3SvcInstalled")) {
2282                 *type = REG_DWORD;
2283                 SIVAL(&data->value, 0, 0x00);
2284                 return WERR_OK;
2285         }
2286
2287         if (!strcasecmp_m(value, "BeepEnabled")) {
2288                 *type = REG_DWORD;
2289                 SIVAL(&data->value, 0, 0x00);
2290                 return WERR_OK;
2291         }
2292
2293         if (!strcasecmp_m(value, "EventLog")) {
2294                 *type = REG_DWORD;
2295                 /* formally was 0x1b */
2296                 SIVAL(&data->value, 0, 0x00);
2297                 return WERR_OK;
2298         }
2299
2300         if (!strcasecmp_m(value, "NetPopup")) {
2301                 *type = REG_DWORD;
2302                 SIVAL(&data->value, 0, 0x00);
2303                 return WERR_OK;
2304         }
2305
2306         if (!strcasecmp_m(value, "MajorVersion")) {
2307                 *type = REG_DWORD;
2308
2309                 /* Windows NT 4.0 seems to not allow uploading of drivers
2310                    to a server that reports 0x3 as the MajorVersion.
2311                    need to investigate more how Win2k gets around this .
2312                    -- jerry */
2313
2314                 if (RA_WINNT == get_remote_arch()) {
2315                         SIVAL(&data->value, 0, 0x02);
2316                 } else {
2317                         SIVAL(&data->value, 0, 0x03);
2318                 }
2319
2320                 return WERR_OK;
2321         }
2322
2323         if (!strcasecmp_m(value, "MinorVersion")) {
2324                 *type = REG_DWORD;
2325                 SIVAL(&data->value, 0, 0x00);
2326                 return WERR_OK;
2327         }
2328
2329         /* REG_BINARY
2330          *  uint32_t size        = 0x114
2331          *  uint32_t major       = 5
2332          *  uint32_t minor       = [0|1]
2333          *  uint32_t build       = [2195|2600]
2334          *  extra unicode string = e.g. "Service Pack 3"
2335          */
2336         if (!strcasecmp_m(value, "OSVersion")) {
2337                 DATA_BLOB blob;
2338                 enum ndr_err_code ndr_err;
2339                 struct spoolss_OSVersion os;
2340
2341                 os.major                = lp_parm_int(GLOBAL_SECTION_SNUM,
2342                                                       "spoolss", "os_major", 5);
2343                                                       /* Windows 2000 == 5.0 */
2344                 os.minor                = lp_parm_int(GLOBAL_SECTION_SNUM,
2345                                                       "spoolss", "os_minor", 0);
2346                 os.build                = lp_parm_int(GLOBAL_SECTION_SNUM,
2347                                                       "spoolss", "os_build", 2195);
2348                 os.extra_string         = "";   /* leave extra string empty */
2349
2350                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2351                         (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2352                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2353                         return WERR_GENERAL_FAILURE;
2354                 }
2355
2356                 if (DEBUGLEVEL >= 10) {
2357                         NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2358                 }
2359
2360                 *type = REG_BINARY;
2361                 data->binary = blob;
2362
2363                 return WERR_OK;
2364         }
2365
2366
2367         if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2368                 *type = REG_SZ;
2369
2370                 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2371                 W_ERROR_HAVE_NO_MEMORY(data->string);
2372
2373                 return WERR_OK;
2374         }
2375
2376         if (!strcasecmp_m(value, "Architecture")) {
2377                 *type = REG_SZ;
2378                 data->string = talloc_strdup(mem_ctx,
2379                         lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2380                 W_ERROR_HAVE_NO_MEMORY(data->string);
2381
2382                 return WERR_OK;
2383         }
2384
2385         if (!strcasecmp_m(value, "DsPresent")) {
2386                 *type = REG_DWORD;
2387
2388                 /* only show the publish check box if we are a
2389                    member of a AD domain */
2390
2391                 if (lp_security() == SEC_ADS) {
2392                         SIVAL(&data->value, 0, 0x01);
2393                 } else {
2394                         SIVAL(&data->value, 0, 0x00);
2395                 }
2396                 return WERR_OK;
2397         }
2398
2399         if (!strcasecmp_m(value, "DNSMachineName")) {
2400                 const char *hostname = get_mydnsfullname();
2401
2402                 if (!hostname) {
2403                         return WERR_BADFILE;
2404                 }
2405
2406                 *type = REG_SZ;
2407                 data->string = talloc_strdup(mem_ctx, hostname);
2408                 W_ERROR_HAVE_NO_MEMORY(data->string);
2409
2410                 return WERR_OK;
2411         }
2412
2413         *type = REG_NONE;
2414
2415         return WERR_INVALID_PARAM;
2416 }
2417
2418 /****************************************************************
2419  _spoolss_GetPrinterData
2420 ****************************************************************/
2421
2422 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2423                                struct spoolss_GetPrinterData *r)
2424 {
2425         struct spoolss_GetPrinterDataEx r2;
2426
2427         r2.in.handle            = r->in.handle;
2428         r2.in.key_name          = "PrinterDriverData";
2429         r2.in.value_name        = r->in.value_name;
2430         r2.in.offered           = r->in.offered;
2431         r2.out.type             = r->out.type;
2432         r2.out.data             = r->out.data;
2433         r2.out.needed           = r->out.needed;
2434
2435         return _spoolss_GetPrinterDataEx(p, &r2);
2436 }
2437
2438 /*********************************************************
2439  Connect to the client machine.
2440 **********************************************************/
2441
2442 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2443                         struct sockaddr_storage *client_ss, const char *remote_machine)
2444 {
2445         NTSTATUS ret;
2446         struct cli_state *the_cli;
2447         struct sockaddr_storage rm_addr;
2448         char addr[INET6_ADDRSTRLEN];
2449
2450         if ( is_zero_addr(client_ss) ) {
2451                 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2452                         remote_machine));
2453                 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2454                         DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2455                         return false;
2456                 }
2457                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2458         } else {
2459                 rm_addr = *client_ss;
2460                 print_sockaddr(addr, sizeof(addr), &rm_addr);
2461                 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2462                         addr));
2463         }
2464
2465         if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2466                 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2467                         addr));
2468                 return false;
2469         }
2470
2471         /* setup the connection */
2472         ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2473                 &rm_addr, 0, "IPC$", "IPC",
2474                 "", /* username */
2475                 "", /* domain */
2476                 "", /* password */
2477                 0, lp_client_signing());
2478
2479         if ( !NT_STATUS_IS_OK( ret ) ) {
2480                 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2481                         remote_machine ));
2482                 return false;
2483         }
2484
2485         if ( smbXcli_conn_protocol(the_cli->conn) != PROTOCOL_NT1 ) {
2486                 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2487                 cli_shutdown(the_cli);
2488                 return false;
2489         }
2490
2491         /*
2492          * Ok - we have an anonymous connection to the IPC$ share.
2493          * Now start the NT Domain stuff :-).
2494          */
2495
2496         ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2497         if (!NT_STATUS_IS_OK(ret)) {
2498                 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2499                         remote_machine, nt_errstr(ret)));
2500                 cli_shutdown(the_cli);
2501                 return false;
2502         }
2503
2504         return true;
2505 }
2506
2507 /***************************************************************************
2508  Connect to the client.
2509 ****************************************************************************/
2510
2511 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2512                                         uint32_t localprinter,
2513                                         enum winreg_Type type,
2514                                         struct policy_handle *handle,
2515                                         struct notify_back_channel **_chan,
2516                                         struct sockaddr_storage *client_ss,
2517                                         struct messaging_context *msg_ctx)
2518 {
2519         WERROR result;
2520         NTSTATUS status;
2521         struct notify_back_channel *chan;
2522
2523         for (chan = back_channels; chan; chan = chan->next) {
2524                 if (memcmp(&chan->client_address, client_ss,
2525                            sizeof(struct sockaddr_storage)) == 0) {
2526                         break;
2527                 }
2528         }
2529
2530         /*
2531          * If it's the first connection, contact the client
2532          * and connect to the IPC$ share anonymously
2533          */
2534         if (!chan) {
2535                 fstring unix_printer;
2536
2537                 /* the +2 is to strip the leading 2 backslashs */
2538                 fstrcpy(unix_printer, printer + 2);
2539
2540                 chan = talloc_zero(NULL, struct notify_back_channel);
2541                 if (!chan) {
2542                         return false;
2543                 }
2544                 chan->client_address = *client_ss;
2545
2546                 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2547                         TALLOC_FREE(chan);
2548                         return false;
2549                 }
2550
2551                 DLIST_ADD(back_channels, chan);
2552
2553                 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2554                                    receive_notify2_message_list);
2555         }
2556
2557         if (chan->cli_pipe == NULL ||
2558             chan->cli_pipe->binding_handle == NULL) {
2559                 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2560                         "NULL %s for printer %s\n",
2561                         chan->cli_pipe == NULL ?
2562                         "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2563                         printer));
2564                 return false;
2565         }
2566
2567         /*
2568          * Tell the specific printing tdb we want messages for this printer
2569          * by registering our PID.
2570          */
2571
2572         if (!print_notify_register_pid(snum)) {
2573                 DEBUG(0, ("Failed to register our pid for printer %s\n",
2574                           printer));
2575         }
2576
2577         status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2578                                                  talloc_tos(),
2579                                                  printer,
2580                                                  localprinter,
2581                                                  type,
2582                                                  0,
2583                                                  NULL,
2584                                                  handle,
2585                                                  &result);
2586         if (!NT_STATUS_IS_OK(status)) {
2587                 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2588                 result = ntstatus_to_werror(status);
2589         } else if (!W_ERROR_IS_OK(result)) {
2590                 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2591         }
2592
2593         chan->active_connections++;
2594         *_chan = chan;
2595
2596         return (W_ERROR_IS_OK(result));
2597 }
2598
2599 /****************************************************************
2600  ****************************************************************/
2601
2602 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2603                                                              const struct spoolss_NotifyOption *r)
2604 {
2605         struct spoolss_NotifyOption *option;
2606         uint32_t i,k;
2607
2608         if (!r) {
2609                 return NULL;
2610         }
2611
2612         option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2613         if (!option) {
2614                 return NULL;
2615         }
2616
2617         *option = *r;
2618
2619         if (!option->count) {
2620                 return option;
2621         }
2622
2623         option->types = talloc_zero_array(option,
2624                 struct spoolss_NotifyOptionType, option->count);
2625         if (!option->types) {
2626                 talloc_free(option);
2627                 return NULL;
2628         }
2629
2630         for (i=0; i < option->count; i++) {
2631                 option->types[i] = r->types[i];
2632
2633                 if (option->types[i].count) {
2634                         option->types[i].fields = talloc_zero_array(option,
2635                                 union spoolss_Field, option->types[i].count);
2636                         if (!option->types[i].fields) {
2637                                 talloc_free(option);
2638                                 return NULL;
2639                         }
2640                         for (k=0; k<option->types[i].count; k++) {
2641                                 option->types[i].fields[k] =
2642                                         r->types[i].fields[k];
2643                         }
2644                 }
2645         }
2646
2647         return option;
2648 }
2649
2650 /****************************************************************
2651  * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2652  *
2653  * before replying OK: status=0 a rpc call is made to the workstation
2654  * asking ReplyOpenPrinter
2655  *
2656  * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2657  * called from api_spoolss_rffpcnex
2658 ****************************************************************/
2659
2660 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2661                                                      struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2662 {
2663         int snum = -1;
2664         struct spoolss_NotifyOption *option = r->in.notify_options;
2665         struct sockaddr_storage client_ss;
2666         ssize_t client_len;
2667
2668         /* store the notify value in the printer struct */
2669
2670         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2671
2672         if (!Printer) {
2673                 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2674                         "Invalid handle (%s:%u:%u).\n",
2675                         OUR_HANDLE(r->in.handle)));
2676                 return WERR_BADFID;
2677         }
2678
2679         Printer->notify.flags           = r->in.flags;
2680         Printer->notify.options         = r->in.options;
2681         Printer->notify.printerlocal    = r->in.printer_local;
2682         Printer->notify.msg_ctx         = p->msg_ctx;
2683
2684         TALLOC_FREE(Printer->notify.option);
2685         Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2686
2687         fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2688
2689         /* Connect to the client machine and send a ReplyOpenPrinter */
2690
2691         if ( Printer->printer_type == SPLHND_SERVER)
2692                 snum = -1;
2693         else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2694                         !get_printer_snum(p, r->in.handle, &snum, NULL) )
2695                 return WERR_BADFID;
2696
2697         DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2698                   "remote_address is %s\n",
2699                   tsocket_address_string(p->remote_address, p->mem_ctx)));
2700
2701         if (!lp_print_notify_backchannel(snum)) {
2702                 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2703                         "backchannel disabled\n"));
2704                 return WERR_SERVER_UNAVAILABLE;
2705         }
2706
2707         client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2708                                                   (struct sockaddr *) &client_ss,
2709                                                   sizeof(struct sockaddr_storage));
2710         if (client_len < 0) {
2711                 return WERR_NOMEM;
2712         }
2713
2714         if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2715                                         Printer->notify.printerlocal, REG_SZ,
2716                                         &Printer->notify.cli_hnd,
2717                                         &Printer->notify.cli_chan,
2718                                         &client_ss, p->msg_ctx)) {
2719                 return WERR_SERVER_UNAVAILABLE;
2720         }
2721
2722         return WERR_OK;
2723 }
2724
2725 /*******************************************************************
2726  * fill a notify_info_data with the servername
2727  ********************************************************************/
2728
2729 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2730                                        int snum,
2731                                        struct spoolss_Notify *data,
2732                                        print_queue_struct *queue,
2733                                        struct spoolss_PrinterInfo2 *pinfo2,
2734                                        TALLOC_CTX *mem_ctx)
2735 {
2736         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2737 }
2738
2739 /*******************************************************************
2740  * fill a notify_info_data with the printername (not including the servername).
2741  ********************************************************************/
2742
2743 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2744                                         int snum,
2745                                         struct spoolss_Notify *data,
2746                                         print_queue_struct *queue,
2747                                         struct spoolss_PrinterInfo2 *pinfo2,
2748                                         TALLOC_CTX *mem_ctx)
2749 {
2750         /* the notify name should not contain the \\server\ part */
2751         const char *p = strrchr(pinfo2->printername, '\\');
2752
2753         if (!p) {
2754                 p = pinfo2->printername;
2755         } else {
2756                 p++;
2757         }
2758
2759         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2760 }
2761
2762 /*******************************************************************
2763  * fill a notify_info_data with the servicename
2764  ********************************************************************/
2765
2766 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2767                                       int snum,
2768                                       struct spoolss_Notify *data,
2769                                       print_queue_struct *queue,
2770                                       struct spoolss_PrinterInfo2 *pinfo2,
2771                                       TALLOC_CTX *mem_ctx)
2772 {
2773         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2774 }
2775
2776 /*******************************************************************
2777  * fill a notify_info_data with the port name
2778  ********************************************************************/
2779
2780 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2781                                      int snum,
2782                                      struct spoolss_Notify *data,
2783                                      print_queue_struct *queue,
2784                                      struct spoolss_PrinterInfo2 *pinfo2,
2785                                      TALLOC_CTX *mem_ctx)
2786 {
2787         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2788 }
2789
2790 /*******************************************************************
2791  * fill a notify_info_data with the printername
2792  * but it doesn't exist, have to see what to do
2793  ********************************************************************/
2794
2795 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2796                                        int snum,
2797                                        struct spoolss_Notify *data,
2798                                        print_queue_struct *queue,
2799                                        struct spoolss_PrinterInfo2 *pinfo2,
2800                                        TALLOC_CTX *mem_ctx)
2801 {
2802         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2803 }
2804
2805 /*******************************************************************
2806  * fill a notify_info_data with the comment
2807  ********************************************************************/
2808
2809 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2810                                    int snum,
2811                                    struct spoolss_Notify *data,
2812                                    print_queue_struct *queue,
2813                                    struct spoolss_PrinterInfo2 *pinfo2,
2814                                    TALLOC_CTX *mem_ctx)
2815 {
2816         const char *p;
2817
2818         if (*pinfo2->comment == '\0') {
2819                 p = lp_comment(talloc_tos(), snum);
2820         } else {
2821                 p = pinfo2->comment;
2822         }
2823
2824         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2825 }
2826
2827 /*******************************************************************
2828  * fill a notify_info_data with the comment
2829  * location = "Room 1, floor 2, building 3"
2830  ********************************************************************/
2831
2832 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2833                                     int snum,
2834                                     struct spoolss_Notify *data,
2835                                     print_queue_struct *queue,
2836                                     struct spoolss_PrinterInfo2 *pinfo2,
2837                                     TALLOC_CTX *mem_ctx)
2838 {
2839         const char *loc = pinfo2->location;
2840         NTSTATUS status;
2841
2842         status = printer_list_get_printer(mem_ctx,
2843                                           pinfo2->sharename,
2844                                           NULL,
2845                                           &loc,
2846                                           NULL);
2847         if (NT_STATUS_IS_OK(status)) {
2848                 if (loc == NULL) {
2849                         loc = pinfo2->location;
2850                 }
2851         }
2852
2853         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2854 }
2855
2856 /*******************************************************************
2857  * fill a notify_info_data with the device mode
2858  * jfm:xxxx don't to it for know but that's a real problem !!!
2859  ********************************************************************/
2860
2861 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2862                                    int snum,
2863                                    struct spoolss_Notify *data,
2864                                    print_queue_struct *queue,
2865                                    struct spoolss_PrinterInfo2 *pinfo2,
2866                                    TALLOC_CTX *mem_ctx)
2867 {
2868         /* for a dummy implementation we have to zero the fields */
2869         SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2870 }
2871
2872 /*******************************************************************
2873  * fill a notify_info_data with the separator file name
2874  ********************************************************************/
2875
2876 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2877                                    int snum,
2878                                    struct spoolss_Notify *data,
2879                                    print_queue_struct *queue,
2880                                    struct spoolss_PrinterInfo2 *pinfo2,
2881                                    TALLOC_CTX *mem_ctx)
2882 {
2883         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2884 }
2885
2886 /*******************************************************************
2887  * fill a notify_info_data with the print processor
2888  * jfm:xxxx return always winprint to indicate we don't do anything to it
2889  ********************************************************************/
2890
2891 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2892                                            int snum,
2893                                            struct spoolss_Notify *data,
2894                                            print_queue_struct *queue,
2895                                            struct spoolss_PrinterInfo2 *pinfo2,
2896                                            TALLOC_CTX *mem_ctx)
2897 {
2898         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2899 }
2900
2901 /*******************************************************************
2902  * fill a notify_info_data with the print processor options
2903  * jfm:xxxx send an empty string
2904  ********************************************************************/
2905
2906 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2907                                       int snum,
2908                                       struct spoolss_Notify *data,
2909                                       print_queue_struct *queue,
2910                                       struct spoolss_PrinterInfo2 *pinfo2,
2911                                       TALLOC_CTX *mem_ctx)
2912 {
2913         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2914 }
2915
2916 /*******************************************************************
2917  * fill a notify_info_data with the data type
2918  * jfm:xxxx always send RAW as data type
2919  ********************************************************************/
2920
2921 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2922                                     int snum,
2923                                     struct spoolss_Notify *data,
2924                                     print_queue_struct *queue,
2925                                     struct spoolss_PrinterInfo2 *pinfo2,
2926                                     TALLOC_CTX *mem_ctx)
2927 {
2928         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2929 }
2930
2931 /*******************************************************************
2932  * fill a notify_info_data with the security descriptor
2933  * jfm:xxxx send an null pointer to say no security desc
2934  * have to implement security before !
2935  ********************************************************************/
2936
2937 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2938                                          int snum,
2939                                          struct spoolss_Notify *data,
2940                                          print_queue_struct *queue,
2941                                          struct spoolss_PrinterInfo2 *pinfo2,
2942                                          TALLOC_CTX *mem_ctx)
2943 {
2944         SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2945 }
2946
2947 /*******************************************************************
2948  * fill a notify_info_data with the attributes
2949  * jfm:xxxx a samba printer is always shared
2950  ********************************************************************/
2951
2952 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2953                                       int snum,
2954                                       struct spoolss_Notify *data,
2955                                       print_queue_struct *queue,
2956                                       struct spoolss_PrinterInfo2 *pinfo2,
2957                                       TALLOC_CTX *mem_ctx)
2958 {
2959         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2960 }
2961
2962 /*******************************************************************
2963  * fill a notify_info_data with the priority
2964  ********************************************************************/
2965
2966 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2967                                     int snum,
2968                                     struct spoolss_Notify *data,
2969                                     print_queue_struct *queue,
2970                                     struct spoolss_PrinterInfo2 *pinfo2,
2971                                     TALLOC_CTX *mem_ctx)
2972 {
2973         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2974 }
2975
2976 /*******************************************************************
2977  * fill a notify_info_data with the default priority
2978  ********************************************************************/
2979
2980 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2981                                             int snum,
2982                                             struct spoolss_Notify *data,
2983                                             print_queue_struct *queue,
2984                                             struct spoolss_PrinterInfo2 *pinfo2,
2985                                             TALLOC_CTX *mem_ctx)
2986 {
2987         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2988 }
2989
2990 /*******************************************************************
2991  * fill a notify_info_data with the start time
2992  ********************************************************************/
2993
2994 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2995                                       int snum,
2996                                       struct spoolss_Notify *data,
2997                                       print_queue_struct *queue,
2998                                       struct spoolss_PrinterInfo2 *pinfo2,
2999                                       TALLOC_CTX *mem_ctx)
3000 {
3001         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3002 }
3003
3004 /*******************************************************************
3005  * fill a notify_info_data with the until time
3006  ********************************************************************/
3007
3008 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3009                                       int snum,
3010                                       struct spoolss_Notify *data,
3011                                       print_queue_struct *queue,
3012                                       struct spoolss_PrinterInfo2 *pinfo2,
3013                                       TALLOC_CTX *mem_ctx)
3014 {
3015         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3016 }
3017
3018 /*******************************************************************
3019  * fill a notify_info_data with the status
3020  ********************************************************************/
3021
3022 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3023                                   int snum,
3024                                   struct spoolss_Notify *data,
3025                                   print_queue_struct *queue,
3026                                   struct spoolss_PrinterInfo2 *pinfo2,
3027                                   TALLOC_CTX *mem_ctx)
3028 {
3029         print_status_struct status;
3030
3031         print_queue_length(msg_ctx, snum, &status);
3032         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3033 }
3034
3035 /*******************************************************************
3036  * fill a notify_info_data with the number of jobs queued
3037  ********************************************************************/
3038
3039 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3040                                  int snum,
3041                                  struct spoolss_Notify *data,
3042                                  print_queue_struct *queue,
3043                                  struct spoolss_PrinterInfo2 *pinfo2,
3044                                  TALLOC_CTX *mem_ctx)
3045 {
3046         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3047                 data, print_queue_length(msg_ctx, snum, NULL));
3048 }
3049
3050 /*******************************************************************
3051  * fill a notify_info_data with the average ppm
3052  ********************************************************************/
3053
3054 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3055                                        int snum,
3056                                        struct spoolss_Notify *data,
3057                                        print_queue_struct *queue,
3058                                        struct spoolss_PrinterInfo2 *pinfo2,
3059                                        TALLOC_CTX *mem_ctx)
3060 {
3061         /* always respond 8 pages per minutes */
3062         /* a little hard ! */
3063         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3064 }
3065
3066 /*******************************************************************
3067  * fill a notify_info_data with username
3068  ********************************************************************/
3069
3070 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3071                                     int snum,
3072                                     struct spoolss_Notify *data,
3073                                     print_queue_struct *queue,
3074                                     struct spoolss_PrinterInfo2 *pinfo2,
3075                                     TALLOC_CTX *mem_ctx)
3076 {
3077         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3078 }
3079
3080 /*******************************************************************
3081  * fill a notify_info_data with job status
3082  ********************************************************************/
3083
3084 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3085                                       int snum,
3086                                       struct spoolss_Notify *data,
3087                                       print_queue_struct *queue,
3088                                       struct spoolss_PrinterInfo2 *pinfo2,
3089                                       TALLOC_CTX *mem_ctx)
3090 {
3091         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3092 }
3093
3094 /*******************************************************************
3095  * fill a notify_info_data with job name
3096  ********************************************************************/
3097
3098 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3099                                     int snum,
3100                                     struct spoolss_Notify *data,
3101                                     print_queue_struct *queue,
3102                                     struct spoolss_PrinterInfo2 *pinfo2,
3103                                     TALLOC_CTX *mem_ctx)
3104 {
3105         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3106 }
3107
3108 /*******************************************************************
3109  * fill a notify_info_data with job status
3110  ********************************************************************/
3111
3112 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3113                                              int snum,
3114                                              struct spoolss_Notify *data,
3115                                              print_queue_struct *queue,
3116                                              struct spoolss_PrinterInfo2 *pinfo2,
3117                                              TALLOC_CTX *mem_ctx)
3118 {
3119         /*
3120          * Now we're returning job status codes we just return a "" here. JRA.
3121          */
3122
3123         const char *p = "";
3124
3125 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3126         p = "unknown";
3127
3128         switch (queue->status) {
3129         case LPQ_QUEUED:
3130                 p = "Queued";
3131                 break;
3132         case LPQ_PAUSED:
3133                 p = "";    /* NT provides the paused string */
3134                 break;
3135         case LPQ_SPOOLING:
3136                 p = "Spooling";
3137                 break;
3138         case LPQ_PRINTING:
3139                 p = "Printing";
3140                 break;
3141         }
3142 #endif /* NO LONGER NEEDED. */
3143
3144         SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3145 }
3146
3147 /*******************************************************************
3148  * fill a notify_info_data with job time
3149  ********************************************************************/
3150
3151 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3152                                     int snum,
3153                                     struct spoolss_Notify *data,
3154                                     print_queue_struct *queue,
3155                                     struct spoolss_PrinterInfo2 *pinfo2,
3156                                     TALLOC_CTX *mem_ctx)
3157 {
3158         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3159 }
3160
3161 /*******************************************************************
3162  * fill a notify_info_data with job size
3163  ********************************************************************/
3164
3165 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3166                                     int snum,
3167                                     struct spoolss_Notify *data,
3168                                     print_queue_struct *queue,
3169                                     struct spoolss_PrinterInfo2 *pinfo2,
3170                                     TALLOC_CTX *mem_ctx)
3171 {
3172         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3173 }
3174
3175 /*******************************************************************
3176  * fill a notify_info_data with page info
3177  ********************************************************************/
3178 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3179                                        int snum,
3180                                 struct spoolss_Notify *data,
3181                                 print_queue_struct *queue,
3182                                 struct spoolss_PrinterInfo2 *pinfo2,
3183                                 TALLOC_CTX *mem_ctx)
3184 {
3185         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3186 }
3187
3188 /*******************************************************************
3189  * fill a notify_info_data with pages printed info.
3190  ********************************************************************/
3191 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3192                                          int snum,
3193                                 struct spoolss_Notify *data,
3194                                 print_queue_struct *queue,
3195                                 struct spoolss_PrinterInfo2 *pinfo2,
3196                                 TALLOC_CTX *mem_ctx)
3197 {
3198         /* Add code when back-end tracks this */
3199         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3200 }
3201
3202 /*******************************************************************
3203  Fill a notify_info_data with job position.
3204  ********************************************************************/
3205
3206 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3207                                         int snum,
3208                                         struct spoolss_Notify *data,
3209                                         print_queue_struct *queue,
3210                                         struct spoolss_PrinterInfo2 *pinfo2,
3211                                         TALLOC_CTX *mem_ctx)
3212 {
3213         SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3214 }
3215
3216 /*******************************************************************
3217  Fill a notify_info_data with submitted time.
3218  ********************************************************************/
3219
3220 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3221                                           int snum,
3222                                           struct spoolss_Notify *data,
3223                                           print_queue_struct *queue,
3224                                           struct spoolss_PrinterInfo2 *pinfo2,
3225                                           TALLOC_CTX *mem_ctx)
3226 {
3227         data->data.string.string = NULL;
3228         data->data.string.size = 0;
3229
3230         init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3231                                &data->data.string.string,
3232                                &data->data.string.size);
3233
3234 }
3235
3236 struct s_notify_info_data_table
3237 {
3238         enum spoolss_NotifyType type;
3239         uint16_t field;
3240         const char *name;
3241         enum spoolss_NotifyTable variable_type;
3242         void (*fn) (struct messaging_context *msg_ctx,
3243                     int snum, struct spoolss_Notify *data,
3244                     print_queue_struct *queue,
3245                     struct spoolss_PrinterInfo2 *pinfo2,
3246                     TALLOC_CTX *mem_ctx);
3247 };
3248
3249 /* A table describing the various print notification constants and
3250    whether the notification data is a pointer to a variable sized
3251    buffer, a one value uint32_t or a two value uint32_t. */
3252
3253 static const struct s_notify_info_data_table notify_info_data_table[] =
3254 {
3255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME,         "PRINTER_NOTIFY_FIELD_SERVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME,        "PRINTER_NOTIFY_FIELD_PRINTER_NAME",        NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME,          "PRINTER_NOTIFY_FIELD_SHARE_NAME",          NOTIFY_TABLE_STRING,   spoolss_notify_share_name },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME,           "PRINTER_NOTIFY_FIELD_PORT_NAME",           NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME,         "PRINTER_NOTIFY_FIELD_DRIVER_NAME",         NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT,             "PRINTER_NOTIFY_FIELD_COMMENT",             NOTIFY_TABLE_STRING,   spoolss_notify_comment },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION,            "PRINTER_NOTIFY_FIELD_LOCATION",            NOTIFY_TABLE_STRING,   spoolss_notify_location },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE,             "PRINTER_NOTIFY_FIELD_DEVMODE",             NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE,             "PRINTER_NOTIFY_FIELD_SEPFILE",             NOTIFY_TABLE_STRING,   spoolss_notify_sepfile },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR,     "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR",     NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS,          "PRINTER_NOTIFY_FIELD_PARAMETERS",          NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE,            "PRINTER_NOTIFY_FIELD_DATATYPE",            NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR,   spoolss_notify_security_desc },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES,          "PRINTER_NOTIFY_FIELD_ATTRIBUTES",          NOTIFY_TABLE_DWORD,    spoolss_notify_attributes },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY,            "PRINTER_NOTIFY_FIELD_PRIORITY",            NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY,    "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY",    NOTIFY_TABLE_DWORD,    spoolss_notify_default_priority },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME,          "PRINTER_NOTIFY_FIELD_START_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME,          "PRINTER_NOTIFY_FIELD_UNTIL_TIME",          NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS,              "PRINTER_NOTIFY_FIELD_STATUS",              NOTIFY_TABLE_DWORD,    spoolss_notify_status },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING,       "PRINTER_NOTIFY_FIELD_STATUS_STRING",       NOTIFY_TABLE_STRING,   NULL },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS,               "PRINTER_NOTIFY_FIELD_CJOBS",               NOTIFY_TABLE_DWORD,    spoolss_notify_cjobs },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM,         "PRINTER_NOTIFY_FIELD_AVERAGE_PPM",         NOTIFY_TABLE_DWORD,    spoolss_notify_average_ppm },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES,         "PRINTER_NOTIFY_FIELD_TOTAL_PAGES",         NOTIFY_TABLE_DWORD,    NULL },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED,       "PRINTER_NOTIFY_FIELD_PAGES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES,         "PRINTER_NOTIFY_FIELD_TOTAL_BYTES",         NOTIFY_TABLE_DWORD,    NULL },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED,       "PRINTER_NOTIFY_FIELD_BYTES_PRINTED",       NOTIFY_TABLE_DWORD,    NULL },
3281 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINTER_NAME,            "JOB_NOTIFY_FIELD_PRINTER_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_printer_name },
3282 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_MACHINE_NAME,            "JOB_NOTIFY_FIELD_MACHINE_NAME",            NOTIFY_TABLE_STRING,   spoolss_notify_server_name },
3283 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PORT_NAME,               "JOB_NOTIFY_FIELD_PORT_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_port_name },
3284 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_USER_NAME,               "JOB_NOTIFY_FIELD_USER_NAME",               NOTIFY_TABLE_STRING,   spoolss_notify_username },
3285 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_NOTIFY_NAME,             "JOB_NOTIFY_FIELD_NOTIFY_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_username },
3286 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DATATYPE,                "JOB_NOTIFY_FIELD_DATATYPE",                NOTIFY_TABLE_STRING,   spoolss_notify_datatype },
3287 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRINT_PROCESSOR,         "JOB_NOTIFY_FIELD_PRINT_PROCESSOR",         NOTIFY_TABLE_STRING,   spoolss_notify_print_processor },
3288 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PARAMETERS,              "JOB_NOTIFY_FIELD_PARAMETERS",              NOTIFY_TABLE_STRING,   spoolss_notify_parameters },
3289 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DRIVER_NAME,             "JOB_NOTIFY_FIELD_DRIVER_NAME",             NOTIFY_TABLE_STRING,   spoolss_notify_driver_name },
3290 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DEVMODE,                 "JOB_NOTIFY_FIELD_DEVMODE",                 NOTIFY_TABLE_DEVMODE,  spoolss_notify_devmode },
3291 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS,                  "JOB_NOTIFY_FIELD_STATUS",                  NOTIFY_TABLE_DWORD,    spoolss_notify_job_status },
3292 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_STATUS_STRING,           "JOB_NOTIFY_FIELD_STATUS_STRING",           NOTIFY_TABLE_STRING,   spoolss_notify_job_status_string },
3293 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR,     "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR",     NOTIFY_TABLE_SECURITYDESCRIPTOR,   NULL },
3294 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_DOCUMENT,                "JOB_NOTIFY_FIELD_DOCUMENT",                NOTIFY_TABLE_STRING,   spoolss_notify_job_name },
3295 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PRIORITY,                "JOB_NOTIFY_FIELD_PRIORITY",                NOTIFY_TABLE_DWORD,    spoolss_notify_priority },
3296 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_POSITION,                "JOB_NOTIFY_FIELD_POSITION",                NOTIFY_TABLE_DWORD,    spoolss_notify_job_position },
3297 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_SUBMITTED,               "JOB_NOTIFY_FIELD_SUBMITTED",               NOTIFY_TABLE_TIME,     spoolss_notify_submitted_time },
3298 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_START_TIME,              "JOB_NOTIFY_FIELD_START_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_start_time },
3299 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_UNTIL_TIME,              "JOB_NOTIFY_FIELD_UNTIL_TIME",              NOTIFY_TABLE_DWORD,    spoolss_notify_until_time },
3300 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TIME,                    "JOB_NOTIFY_FIELD_TIME",                    NOTIFY_TABLE_DWORD,    spoolss_notify_job_time },
3301 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_PAGES,             "JOB_NOTIFY_FIELD_TOTAL_PAGES",             NOTIFY_TABLE_DWORD,    spoolss_notify_total_pages },
3302 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_PAGES_PRINTED,           "JOB_NOTIFY_FIELD_PAGES_PRINTED",           NOTIFY_TABLE_DWORD,    spoolss_notify_pages_printed },
3303 { JOB_NOTIFY_TYPE,     JOB_NOTIFY_FIELD_TOTAL_BYTES,             "JOB_NOTIFY_FIELD_TOTAL_BYTES",             NOTIFY_TABLE_DWORD,    spoolss_notify_job_size },
3304 };
3305
3306 /*******************************************************************
3307  Return the variable_type of info_data structure.
3308 ********************************************************************/
3309
3310 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3311                                                                   uint16_t field)
3312 {
3313         int i=0;
3314
3315         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3316                 if ( (notify_info_data_table[i].type == type) &&
3317                      (notify_info_data_table[i].field == field) ) {
3318                         return notify_info_data_table[i].variable_type;
3319                 }
3320         }
3321
3322         DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3323
3324         return (enum spoolss_NotifyTable) 0;
3325 }
3326
3327 /****************************************************************************
3328 ****************************************************************************/
3329
3330 static bool search_notify(enum spoolss_NotifyType type,
3331                           uint16_t field,
3332                           int *value)
3333 {
3334         int i;
3335
3336         for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3337                 if (notify_info_data_table[i].type == type &&
3338                     notify_info_data_table[i].field == field &&
3339                     notify_info_data_table[i].fn != NULL) {
3340                         *value = i;
3341                         return true;
3342                 }
3343         }
3344
3345         return false;
3346 }
3347
3348 /****************************************************************************
3349 ****************************************************************************/
3350
3351 static void construct_info_data(struct spoolss_Notify *info_data,
3352                                 enum spoolss_NotifyType type,
3353                                 uint16_t field, int id)
3354 {
3355         info_data->type                 = type;
3356         info_data->field.field          = field;
3357         info_data->variable_type        = variable_type_of_notify_info_data(type, field);
3358         info_data->job_id               = id;
3359 }
3360
3361 /*******************************************************************
3362  *
3363  * fill a notify_info struct with info asked
3364  *
3365  ********************************************************************/
3366
3367 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3368                                           struct printer_handle *print_hnd,
3369                                           struct spoolss_NotifyInfo *info,
3370                                           struct spoolss_PrinterInfo2 *pinfo2,
3371                                           int snum,
3372                                           const struct spoolss_NotifyOptionType *option_type,
3373                                           uint32_t id,
3374                                           TALLOC_CTX *mem_ctx)
3375 {
3376         int field_num,j;
3377         enum spoolss_NotifyType type;
3378         uint16_t field;
3379
3380         struct spoolss_Notify *current_data;
3381
3382         type = option_type->type;
3383
3384         DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3385                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3386                 option_type->count, lp_servicename(talloc_tos(), snum)));
3387
3388         for(field_num=0; field_num < option_type->count; field_num++) {
3389                 field = option_type->fields[field_num].field;
3390
3391                 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3392
3393                 if (!search_notify(type, field, &j) )
3394                         continue;
3395
3396                 info->notifies = talloc_realloc(info, info->notifies,
3397                                                       struct spoolss_Notify,
3398                                                       info->count + 1);
3399                 if (info->notifies == NULL) {
3400                         DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3401                         return false;
3402                 }
3403
3404                 current_data = &info->notifies[info->count];
3405
3406                 construct_info_data(current_data, type, field, id);
3407
3408                 DEBUG(10, ("construct_notify_printer_info: "
3409                            "calling [%s]  snum=%d  printername=[%s])\n",
3410                            notify_info_data_table[j].name, snum,
3411                            pinfo2->printername));
3412
3413                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3414                                              NULL, pinfo2, mem_ctx);
3415
3416                 info->count++;
3417         }
3418
3419         return true;
3420 }
3421
3422 /*******************************************************************
3423  *
3424  * fill a notify_info struct with info asked
3425  *
3426  ********************************************************************/
3427
3428 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3429                                        print_queue_struct *queue,
3430                                        struct spoolss_NotifyInfo *info,
3431                                        struct spoolss_PrinterInfo2 *pinfo2,
3432                                        int snum,
3433                                        const struct spoolss_NotifyOptionType *option_type,
3434                                        uint32_t id,
3435                                        TALLOC_CTX *mem_ctx)
3436 {
3437         int field_num,j;
3438         enum spoolss_NotifyType type;
3439         uint16_t field;
3440         struct spoolss_Notify *current_data;
3441
3442         DEBUG(4,("construct_notify_jobs_info\n"));
3443
3444         type = option_type->type;
3445
3446         DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3447                 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3448                 option_type->count));
3449
3450         for(field_num=0; field_num<option_type->count; field_num++) {
3451                 field = option_type->fields[field_num].field;
3452
3453                 if (!search_notify(type, field, &j) )
3454                         continue;
3455
3456                 info->notifies = talloc_realloc(info, info->notifies,
3457                                                       struct spoolss_Notify,
3458                                                       info->count + 1);
3459                 if (info->notifies == NULL) {
3460                         DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3461                         return false;
3462                 }
3463
3464                 current_data=&(info->notifies[info->count]);
3465
3466                 construct_info_data(current_data, type, field, id);
3467                 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3468                                              queue, pinfo2, mem_ctx);
3469                 info->count++;
3470         }
3471
3472         return true;
3473 }
3474
3475 /*
3476  * JFM: The enumeration is not that simple, it's even non obvious.
3477  *
3478  * let's take an example: I want to monitor the PRINTER SERVER for
3479  * the printer's name and the number of jobs currently queued.
3480  * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3481  * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3482  *
3483  * I have 3 printers on the back of my server.
3484  *
3485  * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3486  * structures.
3487  *   Number     Data                    Id
3488  *      1       printer 1 name          1
3489  *      2       printer 1 cjob          1
3490  *      3       printer 2 name          2
3491  *      4       printer 2 cjob          2
3492  *      5       printer 3 name          3
3493  *      6       printer 3 name          3
3494  *
3495  * that's the print server case, the printer case is even worse.
3496  */
3497
3498 /*******************************************************************
3499  *
3500  * enumerate all printers on the printserver
3501  * fill a notify_info struct with info asked
3502  *
3503  ********************************************************************/
3504
3505 static WERROR printserver_notify_info(struct pipes_struct *p,
3506                                       struct policy_handle *hnd,
3507                                       struct spoolss_NotifyInfo *info,
3508                                       TALLOC_CTX *mem_ctx)
3509 {
3510         int snum;
3511         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3512         int n_services=lp_numservices();
3513         int i;
3514         struct spoolss_NotifyOption *option;
3515         struct spoolss_NotifyOptionType option_type;
3516         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3517         WERROR result;
3518
3519         DEBUG(4,("printserver_notify_info\n"));
3520
3521         if (!Printer)
3522                 return WERR_BADFID;
3523
3524         option = Printer->notify.option;
3525
3526         info->version   = 2;
3527         info->notifies  = NULL;
3528         info->count     = 0;
3529
3530         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3531            sending a ffpcn() request first */
3532
3533         if ( !option )
3534                 return WERR_BADFID;
3535
3536         for (i=0; i<option->count; i++) {
3537                 option_type = option->types[i];
3538
3539                 if (option_type.type != PRINTER_NOTIFY_TYPE)
3540                         continue;
3541
3542                 for (snum = 0; snum < n_services; snum++) {
3543                         if (!lp_browseable(snum) ||
3544                             !lp_snum_ok(snum) ||
3545                             !lp_print_ok(snum)) {
3546                                 continue; /* skip */
3547                         }
3548
3549                         /* Maybe we should use the SYSTEM session_info here... */
3550                         result = winreg_get_printer_internal(mem_ctx,
3551                                                     get_session_info_system(),
3552                                                     p->msg_ctx,
3553                                                     lp_servicename(talloc_tos(), snum),
3554                                                     &pinfo2);
3555                         if (!W_ERROR_IS_OK(result)) {
3556                                 DEBUG(4, ("printserver_notify_info: "
3557                                           "Failed to get printer [%s]\n",
3558                                           lp_servicename(talloc_tos(), snum)));
3559                                 continue;
3560                         }
3561
3562
3563                         construct_notify_printer_info(p->msg_ctx,
3564                                                       Printer, info,
3565                                                       pinfo2, snum,
3566                                                       &option_type, snum,
3567                                                       mem_ctx);
3568
3569                         TALLOC_FREE(pinfo2);
3570                 }
3571         }
3572
3573 #if 0
3574         /*
3575          * Debugging information, don't delete.
3576          */
3577
3578         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3579         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3580         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3581
3582         for (i=0; i<info->count; i++) {
3583                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3584                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3585                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3586         }
3587 #endif
3588
3589         return WERR_OK;
3590 }
3591
3592 /*******************************************************************
3593  *
3594  * fill a notify_info struct with info asked
3595  *
3596  ********************************************************************/
3597
3598 static WERROR printer_notify_info(struct pipes_struct *p,
3599                                   struct policy_handle *hnd,
3600                                   struct spoolss_NotifyInfo *info,
3601                                   TALLOC_CTX *mem_ctx)
3602 {
3603         int snum;
3604         struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3605         int i;
3606         uint32_t id;
3607         struct spoolss_NotifyOption *option;
3608         struct spoolss_NotifyOptionType option_type;
3609         int count,j;
3610         print_queue_struct *queue=NULL;
3611         print_status_struct status;
3612         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3613         WERROR result;
3614
3615         DEBUG(4,("printer_notify_info\n"));
3616
3617         if (!Printer)
3618                 return WERR_BADFID;
3619
3620         option = Printer->notify.option;
3621         id = 0x0;
3622
3623         info->version   = 2;
3624         info->notifies  = NULL;
3625         info->count     = 0;
3626
3627         /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3628            sending a ffpcn() request first */
3629
3630         if ( !option )
3631                 return WERR_BADFID;
3632
3633         if (!get_printer_snum(p, hnd, &snum, NULL)) {
3634                 return WERR_BADFID;
3635         }
3636
3637         /* Maybe we should use the SYSTEM session_info here... */
3638         result = winreg_get_printer_internal(mem_ctx,
3639                                     get_session_info_system(),
3640                                     p->msg_ctx,
3641                                     lp_servicename(talloc_tos(), snum), &pinfo2);
3642         if (!W_ERROR_IS_OK(result)) {
3643                 return WERR_BADFID;
3644         }
3645
3646         /*
3647          * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3648          * correct servername.
3649          */
3650         pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3651         if (pinfo2->servername == NULL) {
3652                 return WERR_NOMEM;
3653         }
3654
3655         for (i=0; i<option->count; i++) {
3656                 option_type = option->types[i];
3657
3658                 switch (option_type.type) {
3659                 case PRINTER_NOTIFY_TYPE:
3660                         if (construct_notify_printer_info(p->msg_ctx,
3661                                                           Printer, info,
3662                                                           pinfo2, snum,
3663                                                           &option_type, id,
3664                                                           mem_ctx)) {
3665                                 id--;
3666                         }
3667                         break;
3668
3669                 case JOB_NOTIFY_TYPE:
3670
3671                         count = print_queue_status(p->msg_ctx, snum, &queue,
3672                                                    &status);
3673
3674                         for (j=0; j<count; j++) {
3675                                 construct_notify_jobs_info(p->msg_ctx,
3676                                                            &queue[j], info,
3677                                                            pinfo2, snum,
3678                                                            &option_type,
3679                                                            queue[j].sysjob,
3680                                                            mem_ctx);
3681                         }
3682
3683                         SAFE_FREE(queue);
3684                         break;
3685                 }
3686         }
3687
3688         /*
3689          * Debugging information, don't delete.
3690          */
3691         /*
3692         DEBUG(1,("dumping the NOTIFY_INFO\n"));
3693         DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3694         DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3695
3696         for (i=0; i<info->count; i++) {
3697                 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3698                 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3699                 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3700         }
3701         */
3702
3703         talloc_free(pinfo2);
3704         return WERR_OK;
3705 }
3706
3707 /****************************************************************
3708  _spoolss_RouterRefreshPrinterChangeNotify
3709 ****************************************************************/
3710
3711 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3712                                                  struct spoolss_RouterRefreshPrinterChangeNotify *r)
3713 {
3714         struct spoolss_NotifyInfo *info;
3715
3716         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3717         WERROR result = WERR_BADFID;
3718
3719         /* we always have a spoolss_NotifyInfo struct */
3720         info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3721         if (!info) {
3722                 result = WERR_NOMEM;
3723                 goto done;
3724         }
3725
3726         *r->out.info = info;
3727
3728         if (!Printer) {
3729                 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3730                         "Invalid handle (%s:%u:%u).\n",
3731                         OUR_HANDLE(r->in.handle)));
3732                 goto done;
3733         }
3734
3735         DEBUG(4,("Printer type %x\n",Printer->printer_type));
3736
3737         /*
3738          *      We are now using the change value, and
3739          *      I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3740          *      I don't have a global notification system, I'm sending back all the
3741          *      information even when _NOTHING_ has changed.
3742          */
3743
3744         /* We need to keep track of the change value to send back in
3745            RRPCN replies otherwise our updates are ignored. */
3746
3747         Printer->notify.fnpcn = true;
3748
3749         if (Printer->notify.cli_chan != NULL &&
3750             Printer->notify.cli_chan->active_connections > 0) {
3751                 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3752                         "Saving change value in request [%x]\n",
3753                         r->in.change_low));
3754                 Printer->notify.change = r->in.change_low;
3755         }
3756
3757         /* just ignore the spoolss_NotifyOption */
3758
3759         switch (Printer->printer_type) {
3760                 case SPLHND_SERVER:
3761                         result = printserver_notify_info(p, r->in.handle,
3762                                                          info, p->mem_ctx);
3763                         break;
3764
3765                 case SPLHND_PRINTER:
3766                         result = printer_notify_info(p, r->in.handle,
3767                                                      info, p->mem_ctx);
3768                         break;
3769         }
3770
3771         Printer->notify.fnpcn = false;
3772
3773 done:
3774         return result;
3775 }
3776
3777 /********************************************************************
3778  ********************************************************************/
3779
3780 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3781                                  const char *servername,
3782                                  const char *printername,
3783                                  const char **printername_p)
3784 {
3785         /* FIXME: add lp_force_printername() */
3786
3787         if (servername == NULL) {
3788                 *printername_p = talloc_strdup(mem_ctx, printername);
3789                 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3790                 return WERR_OK;
3791         }
3792
3793         if (servername[0] == '\\' && servername[1] == '\\') {
3794                 servername += 2;
3795         }
3796
3797         *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3798         W_ERROR_HAVE_NO_MEMORY(*printername_p);
3799
3800         return WERR_OK;
3801 }
3802
3803 /********************************************************************
3804  ********************************************************************/
3805
3806 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3807                                           const char *printername)
3808 {
3809         if (dm == NULL) {
3810                 return;
3811         }
3812
3813         dm->devicename = talloc_strndup(dm, printername,
3814                                         MIN(strlen(printername), 31));
3815 }
3816
3817 /********************************************************************
3818  * construct_printer_info_0
3819  * fill a printer_info_0 struct
3820  ********************************************************************/
3821
3822 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3823                                       const struct auth_session_info *session_info,
3824                                       struct messaging_context *msg_ctx,
3825                                       struct spoolss_PrinterInfo2 *info2,
3826                                       const char *servername,
3827                                       struct spoolss_PrinterInfo0 *r,
3828                                       int snum)
3829 {
3830         int count;
3831         struct printer_session_counter *session_counter;
3832         struct timeval setuptime;
3833         print_status_struct status;
3834         WERROR result;
3835
3836         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3837         if (!W_ERROR_IS_OK(result)) {
3838                 return result;
3839         }
3840
3841         if (servername) {
3842                 r->servername = talloc_strdup(mem_ctx, servername);
3843                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3844         } else {
3845                 r->servername = NULL;
3846         }
3847
3848         count = print_queue_length(msg_ctx, snum, &status);
3849
3850         /* check if we already have a counter for this printer */
3851         for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3852                 if (session_counter->snum == snum)
3853                         break;
3854         }
3855
3856         /* it's the first time, add it to the list */
3857         if (session_counter == NULL) {
3858                 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3859                 W_ERROR_HAVE_NO_MEMORY(session_counter);
3860                 session_counter->snum           = snum;
3861                 session_counter->counter        = 0;
3862                 DLIST_ADD(counter_list, session_counter);
3863         }
3864
3865         /* increment it */
3866         session_counter->counter++;
3867
3868         r->cjobs                        = count;
3869         r->total_jobs                   = 0;
3870         r->total_bytes                  = 0;
3871
3872         get_startup_time(&setuptime);
3873         init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3874
3875         /* JFM:
3876          * the global_counter should be stored in a TDB as it's common to all the clients
3877          * and should be zeroed on samba startup
3878          */
3879         r->global_counter               = session_counter->counter;
3880         r->total_pages                  = 0;
3881         /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3882         SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3883         SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3884         r->free_build                   = SPOOLSS_RELEASE_BUILD;
3885         r->spooling                     = 0;
3886         r->max_spooling                 = 0;
3887         r->session_counter              = session_counter->counter;
3888         r->num_error_out_of_paper       = 0x0;
3889         r->num_error_not_ready          = 0x0;          /* number of print failure */
3890         r->job_error                    = 0x0;
3891         r->number_of_processors         = 0x1;
3892         r->processor_type               = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3893         r->high_part_total_bytes        = 0x0;
3894
3895         /* ChangeID in milliseconds*/
3896         winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3897                                     info2->sharename, &r->change_id);
3898
3899         r->last_error                   = WERR_OK;
3900         r->status                       = nt_printq_status(status.status);
3901         r->enumerate_network_printers   = 0x0;
3902         r->c_setprinter                 = 0x0;
3903         r->processor_architecture       = PROCESSOR_ARCHITECTURE_INTEL;
3904         r->processor_level              = 0x6;          /* 6  ???*/
3905         r->ref_ic                       = 0;
3906         r->reserved2                    = 0;
3907         r->reserved3                    = 0;
3908
3909         return WERR_OK;
3910 }
3911
3912
3913 /********************************************************************
3914  * construct_printer_info1
3915  * fill a spoolss_PrinterInfo1 struct
3916 ********************************************************************/
3917
3918 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3919                                       const struct spoolss_PrinterInfo2 *info2,
3920                                       uint32_t flags,
3921                                       const char *servername,
3922                                       struct spoolss_PrinterInfo1 *r,
3923                                       int snum)
3924 {
3925         WERROR result;
3926
3927         r->flags                = flags;
3928
3929         if (info2->comment == NULL || info2->comment[0] == '\0') {
3930                 r->comment      = lp_comment(mem_ctx, snum);
3931         } else {
3932                 r->comment      = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3933         }
3934         W_ERROR_HAVE_NO_MEMORY(r->comment);
3935
3936         result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3937         if (!W_ERROR_IS_OK(result)) {
3938                 return result;
3939         }
3940
3941         r->description          = talloc_asprintf(mem_ctx, "%s,%s,%s",
3942                                                   r->name,
3943                                                   info2->drivername,
3944                                                   r->comment);
3945         W_ERROR_HAVE_NO_MEMORY(r->description);
3946
3947         return WERR_OK;
3948 }
3949
3950 /********************************************************************
3951  * construct_printer_info2
3952  * fill a spoolss_PrinterInfo2 struct
3953 ********************************************************************/
3954
3955 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3956                                       struct messaging_context *msg_ctx,
3957                                       const struct spoolss_PrinterInfo2 *info2,
3958                                       const char *servername,
3959                                       struct spoolss_PrinterInfo2 *r,
3960                                       int snum)
3961 {
3962         int count;
3963         print_status_struct status;
3964         WERROR result;
3965
3966         count = print_queue_length(msg_ctx, snum, &status);
3967
3968         if (servername) {
3969                 r->servername           = talloc_strdup(mem_ctx, servername);
3970                 W_ERROR_HAVE_NO_MEMORY(r->servername);
3971         } else {
3972                 r->servername           = NULL;
3973         }
3974
3975         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3976         if (!W_ERROR_IS_OK(result)) {
3977                 return result;
3978         }
3979
3980         r->sharename            = lp_servicename(mem_ctx, snum);
3981         W_ERROR_HAVE_NO_MEMORY(r->sharename);
3982         r->portname             = talloc_strdup(mem_ctx, info2->portname);
3983         W_ERROR_HAVE_NO_MEMORY(r->portname);
3984         r->drivername           = talloc_strdup(mem_ctx, info2->drivername);
3985         W_ERROR_HAVE_NO_MEMORY(r->drivername);
3986
3987         if (info2->comment[0] == '\0') {
3988                 r->comment      = lp_comment(mem_ctx, snum);
3989         } else {
3990                 r->comment      = talloc_strdup(mem_ctx, info2->comment);
3991         }
3992         W_ERROR_HAVE_NO_MEMORY(r->comment);
3993
3994         r->location     = talloc_strdup(mem_ctx, info2->location);
3995         if (info2->location[0] == '\0') {
3996                 const char *loc = NULL;
3997                 NTSTATUS nt_status;
3998
3999                 nt_status = printer_list_get_printer(mem_ctx,
4000                                                      info2->sharename,
4001                                                      NULL,
4002                                                      &loc,
4003                                                      NULL);
4004                 if (NT_STATUS_IS_OK(nt_status)) {
4005                         if (loc != NULL) {
4006                                 r->location = talloc_strdup(mem_ctx, loc);
4007                         }
4008                 }
4009         }
4010         W_ERROR_HAVE_NO_MEMORY(r->location);
4011
4012         r->sepfile              = talloc_strdup(mem_ctx, info2->sepfile);
4013         W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4014         r->printprocessor       = talloc_strdup(mem_ctx, info2->printprocessor);
4015         W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4016         r->datatype             = talloc_strdup(mem_ctx, info2->datatype);
4017         W_ERROR_HAVE_NO_MEMORY(r->datatype);
4018         r->parameters           = talloc_strdup(mem_ctx, info2->parameters);
4019         W_ERROR_HAVE_NO_MEMORY(r->parameters);
4020
4021         r->attributes           = info2->attributes;
4022
4023         r->priority             = info2->priority;
4024         r->defaultpriority      = info2->defaultpriority;
4025         r->starttime            = info2->starttime;
4026         r->untiltime            = info2->untiltime;
4027         r->status               = nt_printq_status(status.status);
4028         r->cjobs                = count;
4029         r->averageppm           = info2->averageppm;
4030
4031         if (info2->devmode != NULL) {
4032                 result = copy_devicemode(mem_ctx,
4033                                          info2->devmode,
4034                                          &r->devmode);
4035                 if (!W_ERROR_IS_OK(result)) {
4036                         return result;
4037                 }
4038         } else if (lp_default_devmode(snum)) {
4039                 result = spoolss_create_default_devmode(mem_ctx,
4040                                                         info2->printername,
4041                                                         &r->devmode);
4042                 if (!W_ERROR_IS_OK(result)) {
4043                         return result;
4044                 }
4045         } else {
4046                 r->devmode = NULL;
4047                 DEBUG(8,("Returning NULL Devicemode!\n"));
4048         }
4049
4050         compose_devicemode_devicename(r->devmode, r->printername);
4051
4052         r->secdesc = NULL;
4053
4054         if (info2->secdesc != NULL) {
4055                 /* don't use talloc_steal() here unless you do a deep steal of all
4056                    the SEC_DESC members */
4057
4058                 r->secdesc      = dup_sec_desc(mem_ctx, info2->secdesc);
4059         }
4060
4061         return WERR_OK;
4062 }
4063
4064 /********************************************************************
4065  * construct_printer_info3
4066  * fill a spoolss_PrinterInfo3 struct
4067  ********************************************************************/
4068
4069 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4070                                       const struct spoolss_PrinterInfo2 *info2,
4071                                       const char *servername,
4072                                       struct spoolss_PrinterInfo3 *r,
4073                                       int snum)
4074 {
4075         /* These are the components of the SD we are returning. */
4076
4077         if (info2->secdesc != NULL) {
4078                 /* don't use talloc_steal() here unless you do a deep steal of all
4079                    the SEC_DESC members */
4080
4081                 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4082                 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4083         }
4084
4085         return WERR_OK;
4086 }
4087
4088 /********************************************************************
4089  * construct_printer_info4
4090  * fill a spoolss_PrinterInfo4 struct
4091  ********************************************************************/
4092
4093 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4094                                       const struct spoolss_PrinterInfo2 *info2,
4095                                       const char *servername,
4096                                       struct spoolss_PrinterInfo4 *r,
4097                                       int snum)
4098 {
4099         WERROR result;
4100
4101         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4102         if (!W_ERROR_IS_OK(result)) {
4103                 return result;
4104         }
4105
4106         if (servername) {
4107                 r->servername   = talloc_strdup(mem_ctx, servername);
4108                 W_ERROR_HAVE_NO_MEMORY(r->servername);
4109         } else {
4110                 r->servername = NULL;
4111         }
4112
4113         r->attributes   = info2->attributes;
4114
4115         return WERR_OK;
4116 }
4117
4118 /********************************************************************
4119  * construct_printer_info5
4120  * fill a spoolss_PrinterInfo5 struct
4121  ********************************************************************/
4122
4123 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4124                                       const struct spoolss_PrinterInfo2 *info2,
4125                                       const char *servername,
4126                                       struct spoolss_PrinterInfo5 *r,
4127                                       int snum)
4128 {
4129         WERROR result;
4130
4131         result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4132         if (!W_ERROR_IS_OK(result)) {
4133                 return result;
4134         }
4135
4136         r->portname     = talloc_strdup(mem_ctx, info2->portname);
4137         W_ERROR_HAVE_NO_MEMORY(r->portname);
4138
4139         r->attributes   = info2->attributes;
4140
4141         /* these two are not used by NT+ according to MSDN */
4142         r->device_not_selected_timeout          = 0x0;  /* have seen 0x3a98 */
4143         r->transmission_retry_timeout           = 0x0;  /* have seen 0xafc8 */
4144
4145         return WERR_OK;
4146 }
4147
4148 /********************************************************************
4149  * construct_printer_info_6
4150  * fill a spoolss_PrinterInfo6 struct
4151  ********************************************************************/
4152
4153 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4154                                       struct messaging_context *msg_ctx,
4155                                       const struct spoolss_PrinterInfo2 *info2,
4156                                       const char *servername,
4157                                       struct spoolss_PrinterInfo6 *r,
4158                                       int snum)
4159 {
4160         print_status_struct status;
4161
4162         print_queue_length(msg_ctx, snum, &status);
4163
4164         r->status = nt_printq_status(status.status);
4165
4166         return WERR_OK;
4167 }
4168
4169 /********************************************************************
4170  * construct_printer_info7
4171  * fill a spoolss_PrinterInfo7 struct
4172  ********************************************************************/
4173
4174 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4175                                       struct messaging_context *msg_ctx,
4176                                       const char *servername,
4177                                       struct spoolss_PrinterInfo7 *r,
4178                                       int snum)
4179 {
4180         const struct auth_session_info *session_info;
4181         char *printer;
4182         WERROR werr;
4183         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4184         if (tmp_ctx == NULL) {
4185                 return WERR_NOMEM;
4186         }
4187
4188         session_info = get_session_info_system();
4189         SMB_ASSERT(session_info != NULL);
4190
4191         printer = lp_servicename(tmp_ctx, snum);
4192         if (printer == NULL) {
4193                 DEBUG(0, ("invalid printer snum %d\n", snum));
4194                 werr = WERR_INVALID_PARAM;
4195                 goto out_tmp_free;
4196         }
4197
4198         if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4199                                  servername, printer, NULL)) {
4200                 struct GUID guid;
4201                 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4202                                            printer, &guid);
4203                 if (!W_ERROR_IS_OK(werr)) {
4204                         goto out_tmp_free;
4205                 }
4206                 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4207                 r->action = DSPRINT_PUBLISH;
4208         } else {
4209                 r->guid = talloc_strdup(mem_ctx, "");
4210                 r->action = DSPRINT_UNPUBLISH;
4211         }
4212         if (r->guid == NULL) {
4213                 werr = WERR_NOMEM;
4214                 goto out_tmp_free;
4215         }
4216
4217         werr = WERR_OK;
4218 out_tmp_free:
4219         talloc_free(tmp_ctx);
4220         return werr;
4221 }
4222
4223 /********************************************************************
4224  * construct_printer_info8
4225  * fill a spoolss_PrinterInfo8 struct
4226  ********************************************************************/
4227
4228 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4229                                       const struct spoolss_PrinterInfo2 *info2,
4230                                       const char *servername,
4231                                       struct spoolss_DeviceModeInfo *r,
4232                                       int snum)
4233 {
4234         WERROR result;
4235         const char *printername;
4236
4237         result = create_printername(mem_ctx, servername, info2->printername, &printername);
4238         if (!W_ERROR_IS_OK(result)) {
4239                 return result;
4240         }
4241
4242         if (info2->devmode != NULL) {
4243                 result = copy_devicemode(mem_ctx,
4244                                          info2->devmode,
4245                                          &r->devmode);
4246                 if (!W_ERROR_IS_OK(result)) {
4247                         return result;
4248                 }
4249         } else if (lp_default_devmode(snum)) {
4250                 result = spoolss_create_default_devmode(mem_ctx,
4251                                                         info2->printername,
4252                                                         &r->devmode);
4253                 if (!W_ERROR_IS_OK(result)) {
4254                         return result;
4255                 }
4256         } else {
4257                 r->devmode = NULL;
4258                 DEBUG(8,("Returning NULL Devicemode!\n"));
4259         }
4260
4261         compose_devicemode_devicename(r->devmode, printername);
4262
4263         return WERR_OK;
4264 }
4265
4266
4267 /********************************************************************
4268 ********************************************************************/
4269
4270 static bool snum_is_shared_printer(int snum)
4271 {
4272         return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4273 }
4274
4275 /********************************************************************
4276  Spoolss_enumprinters.
4277 ********************************************************************/
4278
4279 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4280                                            const struct auth_session_info *session_info,
4281                                            struct messaging_context *msg_ctx,
4282                                            const char *servername,
4283                                            uint32_t level,
4284                                            uint32_t flags,
4285                                            union spoolss_PrinterInfo **info_p,
4286                                            uint32_t *count_p)
4287 {
4288         int snum;
4289         int n_services = lp_numservices();
4290         union spoolss_PrinterInfo *info = NULL;
4291         uint32_t count = 0;
4292         WERROR result = WERR_OK;
4293         struct dcerpc_binding_handle *b = NULL;
4294         TALLOC_CTX *tmp_ctx = NULL;
4295
4296         tmp_ctx = talloc_new(mem_ctx);
4297         if (!tmp_ctx) {
4298                 return WERR_NOMEM;
4299         }
4300
4301         *count_p = 0;
4302         *info_p = NULL;
4303
4304         for (snum = 0; snum < n_services; snum++) {
4305
4306                 const char *printer;
4307                 struct spoolss_PrinterInfo2 *info2;
4308
4309                 if (!snum_is_shared_printer(snum)) {
4310                         continue;
4311                 }
4312
4313                 printer = lp_const_servicename(snum);
4314
4315                 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4316                         printer, snum));
4317
4318                 if (b == NULL) {
4319                         result = winreg_printer_binding_handle(tmp_ctx,
4320                                                                session_info,
4321                                                                msg_ctx,
4322                                                                &b);
4323                         if (!W_ERROR_IS_OK(result)) {
4324                                 goto out;
4325                         }
4326                 }
4327
4328                 result = winreg_create_printer(tmp_ctx, b,
4329                                                printer);
4330                 if (!W_ERROR_IS_OK(result)) {
4331                         goto out;
4332                 }
4333
4334                 info = talloc_realloc(tmp_ctx, info,
4335                                             union spoolss_PrinterInfo,
4336                                             count + 1);
4337                 if (!info) {
4338                         result = WERR_NOMEM;
4339                         goto out;
4340                 }
4341
4342                 result = winreg_get_printer(tmp_ctx, b,
4343                                             printer, &info2);
4344                 if (!W_ERROR_IS_OK(result)) {
4345                         goto out;
4346                 }
4347
4348                 switch (level) {
4349                 case 0:
4350                         result = construct_printer_info0(info, session_info,
4351                                                          msg_ctx, info2,
4352                                                          servername,
4353                                                          &info[count].info0, snum);
4354                         break;
4355                 case 1:
4356                         result = construct_printer_info1(info, info2, flags,
4357                                                          servername,
4358                                                          &info[count].info1, snum);
4359                         break;
4360                 case 2:
4361                         result = construct_printer_info2(info, msg_ctx, info2,
4362                                                          servername,
4363                                                          &info[count].info2, snum);
4364                         break;
4365                 case 4:
4366                         result = construct_printer_info4(info, info2,
4367                                                          servername,
4368                                                          &info[count].info4, snum);
4369                         break;
4370                 case 5:
4371                         result = construct_printer_info5(info, info2,
4372                                                          servername,
4373                                                          &info[count].info5, snum);
4374                         break;
4375
4376                 default:
4377                         result = WERR_UNKNOWN_LEVEL;
4378                         goto out;
4379                 }
4380
4381                 if (!W_ERROR_IS_OK(result)) {
4382                         goto out;
4383                 }
4384
4385                 count++;
4386         }
4387
4388 out:
4389         if (W_ERROR_IS_OK(result)) {
4390                 *info_p = talloc_move(mem_ctx, &info);
4391                 *count_p = count;
4392         }
4393
4394         talloc_free(tmp_ctx);
4395
4396         return result;
4397 }
4398
4399 /********************************************************************
4400  * handle enumeration of printers at level 0
4401  ********************************************************************/
4402
4403 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4404                                   const struct auth_session_info *session_info,
4405                                   struct messaging_context *msg_ctx,
4406                                   uint32_t flags,
4407                                   const char *servername,
4408                                   union spoolss_PrinterInfo **info,
4409                                   uint32_t *count)
4410 {
4411         DEBUG(4,("enum_all_printers_info_0\n"));
4412
4413         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4414                                             servername, 0, flags, info, count);
4415 }
4416
4417
4418 /********************************************************************
4419 ********************************************************************/
4420
4421 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4422                                        const struct auth_session_info *session_info,
4423                                        struct messaging_context *msg_ctx,
4424                                        const char *servername,
4425                                        uint32_t flags,
4426                                        union spoolss_PrinterInfo **info,
4427                                        uint32_t *count)
4428 {
4429         DEBUG(4,("enum_all_printers_info_1\n"));
4430
4431         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4432                                             servername, 1, flags, info, count);
4433 }
4434
4435 /********************************************************************
4436  enum_all_printers_info_1_local.
4437 *********************************************************************/
4438
4439 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4440                                              const struct auth_session_info *session_info,
4441                                              struct messaging_context *msg_ctx,
4442                                              const char *servername,
4443                                              union spoolss_PrinterInfo **info,
4444                                              uint32_t *count)
4445 {
4446         DEBUG(4,("enum_all_printers_info_1_local\n"));
4447
4448         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4449                                         servername, PRINTER_ENUM_ICON8, info, count);
4450 }
4451
4452 /********************************************************************
4453  enum_all_printers_info_1_name.
4454 *********************************************************************/
4455
4456 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4457                                             const struct auth_session_info *session_info,
4458                                             struct messaging_context *msg_ctx,
4459                                             const char *servername,
4460                                             union spoolss_PrinterInfo **info,
4461                                             uint32_t *count)
4462 {
4463         const char *s = servername;
4464
4465         DEBUG(4,("enum_all_printers_info_1_name\n"));
4466
4467         if (servername != NULL &&
4468             (servername[0] == '\\') && (servername[1] == '\\')) {
4469                 s = servername + 2;
4470         }
4471
4472         if (!is_myname_or_ipaddr(s)) {
4473                 return WERR_INVALID_NAME;
4474         }
4475
4476         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4477                                         servername, PRINTER_ENUM_ICON8, info, count);
4478 }
4479
4480 /********************************************************************
4481  enum_all_printers_info_1_network.
4482 *********************************************************************/
4483
4484 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4485                                                const struct auth_session_info *session_info,
4486                                                struct messaging_context *msg_ctx,
4487                                                const char *servername,
4488                                                union spoolss_PrinterInfo **info,
4489                                                uint32_t *count)
4490 {
4491         const char *s = servername;
4492
4493         DEBUG(4,("enum_all_printers_info_1_network\n"));
4494
4495         /* If we respond to a enum_printers level 1 on our name with flags
4496            set to PRINTER_ENUM_REMOTE with a list of printers then these
4497            printers incorrectly appear in the APW browse list.
4498            Specifically the printers for the server appear at the workgroup
4499            level where all the other servers in the domain are
4500            listed. Windows responds to this call with a
4501            WERR_CAN_NOT_COMPLETE so we should do the same. */
4502
4503         if (servername != NULL &&
4504             (servername[0] == '\\') && (servername[1] == '\\')) {
4505                  s = servername + 2;
4506         }
4507
4508         if (is_myname_or_ipaddr(s)) {
4509                  return WERR_CAN_NOT_COMPLETE;
4510         }
4511
4512         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4513                                         servername, PRINTER_ENUM_NAME, info, count);
4514 }
4515
4516 /********************************************************************
4517  * api_spoolss_enumprinters
4518  *
4519  * called from api_spoolss_enumprinters (see this to understand)
4520  ********************************************************************/
4521
4522 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4523                                        const struct auth_session_info *session_info,
4524                                        struct messaging_context *msg_ctx,
4525                                        const char *servername,
4526                                        union spoolss_PrinterInfo **info,
4527                                        uint32_t *count)
4528 {
4529         DEBUG(4,("enum_all_printers_info_2\n"));
4530
4531         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4532                                             servername, 2, 0, info, count);
4533 }
4534
4535 /********************************************************************
4536  * handle enumeration of printers at level 1
4537  ********************************************************************/
4538
4539 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4540                                   const struct auth_session_info *session_info,
4541                                   struct messaging_context *msg_ctx,
4542                                   uint32_t flags,
4543                                   const char *servername,
4544                                   union spoolss_PrinterInfo **info,
4545                                   uint32_t *count)
4546 {
4547         /* Not all the flags are equals */
4548
4549         if (flags & PRINTER_ENUM_LOCAL) {
4550                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4551                                                       msg_ctx, servername, info, count);
4552         }
4553
4554         if (flags & PRINTER_ENUM_NAME) {
4555                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4556                                                      msg_ctx, servername, info,
4557                                                      count);
4558         }
4559
4560         if (flags & PRINTER_ENUM_NETWORK) {
4561                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4562                                                         msg_ctx, servername, info,
4563                                                         count);
4564         }
4565
4566         return WERR_OK; /* NT4sp5 does that */
4567 }
4568
4569 /********************************************************************
4570  * handle enumeration of printers at level 2
4571  ********************************************************************/
4572
4573 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4574                                   const struct auth_session_info *session_info,
4575                                   struct messaging_context *msg_ctx,
4576                                   uint32_t flags,
4577                                   const char *servername,
4578                                   union spoolss_PrinterInfo **info,
4579                                   uint32_t *count)
4580 {
4581         if (flags & PRINTER_ENUM_LOCAL) {
4582
4583                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4584                                                 servername,
4585                                                 info, count);
4586         }
4587
4588         if (flags & PRINTER_ENUM_NAME) {
4589                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4590                         return WERR_INVALID_NAME;
4591                 }
4592
4593                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4594                                                 servername,
4595                                                 info, count);
4596         }
4597
4598         if (flags & PRINTER_ENUM_REMOTE) {
4599                 return WERR_UNKNOWN_LEVEL;
4600         }
4601
4602         return WERR_OK;
4603 }
4604
4605 /********************************************************************
4606  * handle enumeration of printers at level 4
4607  ********************************************************************/
4608
4609 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4610                                   const struct auth_session_info *session_info,
4611                                   struct messaging_context *msg_ctx,
4612                                   uint32_t flags,
4613                                   const char *servername,
4614                                   union spoolss_PrinterInfo **info,
4615                                   uint32_t *count)
4616 {
4617         DEBUG(4,("enum_all_printers_info_4\n"));
4618
4619         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4620                                             servername, 4, flags, info, count);
4621 }
4622
4623
4624 /********************************************************************
4625  * handle enumeration of printers at level 5
4626  ********************************************************************/
4627
4628 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4629                                   const struct auth_session_info *session_info,
4630                                   struct messaging_context *msg_ctx,
4631                                   uint32_t flags,
4632                                   const char *servername,
4633                                   union spoolss_PrinterInfo **info,
4634                                   uint32_t *count)
4635 {
4636         DEBUG(4,("enum_all_printers_info_5\n"));
4637
4638         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4639                                             servername, 5, flags, info, count);
4640 }
4641
4642 /****************************************************************
4643  _spoolss_EnumPrinters
4644 ****************************************************************/
4645
4646 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4647                              struct spoolss_EnumPrinters *r)
4648 {
4649         const struct auth_session_info *session_info = get_session_info_system();
4650         WERROR result;
4651
4652         /* that's an [in out] buffer */
4653
4654         if (!r->in.buffer && (r->in.offered != 0)) {
4655                 return WERR_INVALID_PARAM;
4656         }
4657
4658         DEBUG(4,("_spoolss_EnumPrinters\n"));
4659
4660         *r->out.needed = 0;
4661         *r->out.count = 0;
4662         *r->out.info = NULL;
4663
4664         /*
4665          * Level 1:
4666          *          flags==PRINTER_ENUM_NAME
4667          *           if name=="" then enumerates all printers
4668          *           if name!="" then enumerate the printer
4669          *          flags==PRINTER_ENUM_REMOTE
4670          *          name is NULL, enumerate printers
4671          * Level 2: name!="" enumerates printers, name can't be NULL
4672          * Level 3: doesn't exist
4673          * Level 4: does a local registry lookup
4674          * Level 5: same as Level 2
4675          */
4676
4677         if (r->in.server && r->in.server[0] == '\0') {
4678                 r->in.server = NULL;
4679         }
4680
4681         switch (r->in.level) {
4682         case 0:
4683                 result = enumprinters_level0(p->mem_ctx, session_info,
4684                                              p->msg_ctx, r->in.flags,
4685                                              r->in.server,
4686                                              r->out.info, r->out.count);
4687                 break;
4688         case 1:
4689                 result = enumprinters_level1(p->mem_ctx, session_info,
4690                                              p->msg_ctx, r->in.flags,
4691                                              r->in.server,
4692                                              r->out.info, r->out.count);
4693                 break;
4694         case 2:
4695                 result = enumprinters_level2(p->mem_ctx, session_info,
4696                                              p->msg_ctx, r->in.flags,
4697                                              r->in.server,
4698                                              r->out.info, r->out.count);
4699                 break;
4700         case 4:
4701                 result = enumprinters_level4(p->mem_ctx, session_info,
4702                                              p->msg_ctx, r->in.flags,
4703                                              r->in.server,
4704                                              r->out.info, r->out.count);
4705                 break;
4706         case 5:
4707                 result = enumprinters_level5(p->mem_ctx, session_info,
4708                                              p->msg_ctx, r->in.flags,
4709                                              r->in.server,
4710                                              r->out.info, r->out.count);
4711                 break;
4712         default:
4713                 return WERR_UNKNOWN_LEVEL;
4714         }
4715
4716         if (!W_ERROR_IS_OK(result)) {
4717                 return result;
4718         }
4719
4720         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4721                                                      spoolss_EnumPrinters,
4722                                                      *r->out.info, r->in.level,
4723                                                      *r->out.count);
4724         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4725         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4726
4727         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4728 }
4729
4730 /****************************************************************
4731  _spoolss_GetPrinter
4732 ****************************************************************/
4733
4734 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4735                            struct spoolss_GetPrinter *r)
4736 {
4737         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4738         struct spoolss_PrinterInfo2 *info2 = NULL;
4739         WERROR result = WERR_OK;
4740         int snum;
4741
4742         /* that's an [in out] buffer */
4743
4744         if (!r->in.buffer && (r->in.offered != 0)) {
4745                 return WERR_INVALID_PARAM;
4746         }
4747
4748         *r->out.needed = 0;
4749
4750         if (Printer == NULL) {
4751                 return WERR_BADFID;
4752         }
4753
4754         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4755                 return WERR_BADFID;
4756         }
4757
4758         result = winreg_get_printer_internal(p->mem_ctx,
4759                                     get_session_info_system(),
4760                                     p->msg_ctx,
4761                                     lp_const_servicename(snum),
4762                                     &info2);
4763         if (!W_ERROR_IS_OK(result)) {
4764                 goto out;
4765         }
4766
4767         switch (r->in.level) {
4768         case 0:
4769                 result = construct_printer_info0(p->mem_ctx,
4770                                                  get_session_info_system(),
4771                                                  p->msg_ctx,
4772                                                  info2,
4773                                                  Printer->servername,
4774                                                  &r->out.info->info0,
4775                                                  snum);
4776                 break;
4777         case 1:
4778                 result = construct_printer_info1(p->mem_ctx, info2,
4779                                                  PRINTER_ENUM_ICON8,
4780                                                  Printer->servername,
4781                                                  &r->out.info->info1, snum);
4782                 break;
4783         case 2:
4784                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4785                                                  Printer->servername,
4786                                                  &r->out.info->info2, snum);
4787                 break;
4788         case 3:
4789                 result = construct_printer_info3(p->mem_ctx, info2,
4790                                                  Printer->servername,
4791                                                  &r->out.info->info3, snum);
4792                 break;
4793         case 4:
4794                 result = construct_printer_info4(p->mem_ctx, info2,
4795                                                  Printer->servername,
4796                                                  &r->out.info->info4, snum);
4797                 break;
4798         case 5:
4799                 result = construct_printer_info5(p->mem_ctx, info2,
4800                                                  Printer->servername,
4801                                                  &r->out.info->info5, snum);
4802                 break;
4803         case 6:
4804                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4805                                                  Printer->servername,
4806                                                  &r->out.info->info6, snum);
4807                 break;
4808         case 7:
4809                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4810                                                  Printer->servername,
4811                                                  &r->out.info->info7, snum);
4812                 break;
4813         case 8:
4814                 result = construct_printer_info8(p->mem_ctx, info2,
4815                                                  Printer->servername,
4816                                                  &r->out.info->info8, snum);
4817                 break;
4818         default:
4819                 result = WERR_UNKNOWN_LEVEL;
4820                 break;
4821         }
4822         TALLOC_FREE(info2);
4823
4824  out:
4825         if (!W_ERROR_IS_OK(result)) {
4826                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4827                           r->in.level, win_errstr(result)));
4828                 TALLOC_FREE(r->out.info);
4829                 return result;
4830         }
4831
4832         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4833                                                r->out.info, r->in.level);
4834         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4835
4836         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4837 }
4838
4839 /********************************************************************
4840  ********************************************************************/
4841
4842 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4843         do { \
4844                 if (in && strlen(in)) { \
4845                         out = talloc_strdup(mem_ctx, in); \
4846                 } else { \
4847                         out = talloc_strdup(mem_ctx, ""); \
4848                 } \
4849                 W_ERROR_HAVE_NO_MEMORY(out); \
4850         } while (0);
4851
4852 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4853         do { \
4854                 if (in && strlen(in)) { \
4855                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4856                 } else { \
4857                         out = talloc_strdup(mem_ctx, ""); \
4858                 } \
4859                 W_ERROR_HAVE_NO_MEMORY(out); \
4860         } while (0);
4861
4862 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4863                                                   const char **string_array,
4864                                                   const char ***presult,
4865                                                   const char *cservername,
4866                                                   const char *arch,
4867                                                   int version)
4868 {
4869         int i, num_strings = 0;
4870         const char **array = NULL;
4871
4872         if (string_array == NULL) {
4873                 return WERR_INVALID_PARAMETER;
4874         }
4875
4876         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4877                 const char *str = NULL;
4878
4879                 if (cservername == NULL || arch == NULL) {
4880                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4881                 } else {
4882                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4883                 }
4884
4885                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4886                         TALLOC_FREE(array);
4887                         return WERR_NOMEM;
4888                 }
4889         }
4890
4891         if (i > 0) {
4892                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4893                              &array, &num_strings);
4894         }
4895
4896         if (presult != NULL) {
4897                 *presult = array;
4898         } else {
4899                 talloc_free(array);
4900         }
4901
4902         return WERR_OK;
4903 }
4904
4905 /********************************************************************
4906  * fill a spoolss_DriverInfo1 struct
4907  ********************************************************************/
4908
4909 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4910                                         struct spoolss_DriverInfo1 *r,
4911                                         const struct spoolss_DriverInfo8 *driver,
4912                                         const char *servername)
4913 {
4914         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4915         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4916
4917         return WERR_OK;
4918 }
4919
4920 /********************************************************************
4921  * fill a spoolss_DriverInfo2 struct
4922  ********************************************************************/
4923
4924 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4925                                         struct spoolss_DriverInfo2 *r,
4926                                         const struct spoolss_DriverInfo8 *driver,
4927                                         const char *servername)
4928
4929 {
4930         const char *cservername = canon_servername(servername);
4931
4932         r->version              = driver->version;
4933
4934         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4935         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4936         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4937         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4938
4939         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4940                                driver->architecture,
4941                                driver->version,
4942                                driver->driver_path,
4943                                r->driver_path);
4944
4945         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4946                                driver->architecture,
4947                                driver->version,
4948                                driver->data_file,
4949                                r->data_file);
4950
4951         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4952                                driver->architecture,
4953                                driver->version,
4954                                driver->config_file,
4955                                r->config_file);
4956
4957         return WERR_OK;
4958 }
4959
4960 /********************************************************************
4961  * fill a spoolss_DriverInfo3 struct
4962  ********************************************************************/
4963
4964 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4965                                         struct spoolss_DriverInfo3 *r,
4966                                         const struct spoolss_DriverInfo8 *driver,
4967                                         const char *servername)
4968 {
4969         const char *cservername = canon_servername(servername);
4970
4971         r->version              = driver->version;
4972
4973         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4974         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4975         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4976         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4977
4978         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4979                                driver->architecture,
4980                                driver->version,
4981                                driver->driver_path,
4982                                r->driver_path);
4983
4984         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4985                                driver->architecture,
4986                                driver->version,
4987                                driver->data_file,
4988                                r->data_file);
4989
4990         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4991                                driver->architecture,
4992                                driver->version,
4993                                driver->config_file,
4994                                r->config_file);
4995
4996         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4997                                driver->architecture,
4998                                driver->version,
4999                                driver->help_file,
5000                                r->help_file);
5001
5002         FILL_DRIVER_STRING(mem_ctx,
5003                            driver->monitor_name,
5004                            r->monitor_name);
5005
5006         FILL_DRIVER_STRING(mem_ctx,
5007                            driver->default_datatype,
5008                            r->default_datatype);
5009
5010         return string_array_from_driver_info(mem_ctx,
5011                                              driver->dependent_files,
5012                                              &r->dependent_files,
5013                                              cservername,
5014                                              driver->architecture,
5015                                              driver->version);
5016 }
5017
5018 /********************************************************************
5019  * fill a spoolss_DriverInfo4 struct
5020  ********************************************************************/
5021
5022 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5023                                         struct spoolss_DriverInfo4 *r,
5024                                         const struct spoolss_DriverInfo8 *driver,
5025                                         const char *servername)
5026 {
5027         const char *cservername = canon_servername(servername);
5028         WERROR result;
5029
5030         r->version              = driver->version;
5031
5032         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5033         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5034         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5035         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5036
5037         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5038                                driver->architecture,
5039                                driver->version,
5040                                driver->driver_path,
5041                                r->driver_path);
5042
5043         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5044                                driver->architecture,
5045                                driver->version,
5046                                driver->data_file,
5047                                r->data_file);
5048
5049         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5050                                driver->architecture,
5051                                driver->version,
5052                                driver->config_file,
5053                                r->config_file);
5054
5055         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5056                                driver->architecture,
5057                                driver->version,
5058                                driver->help_file,
5059                                r->help_file);
5060
5061         result = string_array_from_driver_info(mem_ctx,
5062                                                driver->dependent_files,
5063                                                &r->dependent_files,
5064                                                cservername,
5065                                                driver->architecture,
5066                                                driver->version);
5067         if (!W_ERROR_IS_OK(result)) {
5068                 return result;
5069         }
5070
5071         FILL_DRIVER_STRING(mem_ctx,
5072                            driver->monitor_name,
5073                            r->monitor_name);
5074
5075         FILL_DRIVER_STRING(mem_ctx,
5076                            driver->default_datatype,
5077                            r->default_datatype);
5078
5079
5080         result = string_array_from_driver_info(mem_ctx,
5081                                                driver->previous_names,
5082                                                &r->previous_names,
5083                                                NULL, NULL, 0);
5084
5085         return result;
5086 }
5087
5088 /********************************************************************
5089  * fill a spoolss_DriverInfo5 struct
5090  ********************************************************************/
5091
5092 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5093                                         struct spoolss_DriverInfo5 *r,
5094                                         const struct spoolss_DriverInfo8 *driver,
5095                                         const char *servername)
5096 {
5097         const char *cservername = canon_servername(servername);
5098
5099         r->version              = driver->version;
5100
5101         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5102         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5103         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5104         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5105
5106         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5107                                driver->architecture,
5108                                driver->version,
5109                                driver->driver_path,
5110                                r->driver_path);
5111
5112         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5113                                driver->architecture,
5114                                driver->version,
5115                                driver->data_file,
5116                                r->data_file);
5117
5118         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5119                                driver->architecture,
5120                                driver->version,
5121                                driver->config_file,
5122                                r->config_file);
5123
5124         r->driver_attributes    = 0;
5125         r->config_version       = 0;
5126         r->driver_version       = 0;
5127
5128         return WERR_OK;
5129 }
5130 /********************************************************************
5131  * fill a spoolss_DriverInfo6 struct
5132  ********************************************************************/
5133
5134 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5135                                         struct spoolss_DriverInfo6 *r,
5136                                         const struct spoolss_DriverInfo8 *driver,
5137                                         const char *servername)
5138 {
5139         const char *cservername = canon_servername(servername);
5140         WERROR result;
5141
5142         r->version              = driver->version;
5143
5144         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5145         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5146         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5147         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5148
5149         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5150                                driver->architecture,
5151                                driver->version,
5152                                driver->driver_path,
5153                                r->driver_path);
5154
5155         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5156                                driver->architecture,
5157                                driver->version,
5158                                driver->data_file,
5159                                r->data_file);
5160
5161         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5162                                driver->architecture,
5163                                driver->version,
5164                                driver->config_file,
5165                                r->config_file);
5166
5167         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5168                                driver->architecture,
5169                                driver->version,
5170                                driver->help_file,
5171                                r->help_file);
5172
5173         FILL_DRIVER_STRING(mem_ctx,
5174                            driver->monitor_name,
5175                            r->monitor_name);
5176
5177         FILL_DRIVER_STRING(mem_ctx,
5178                            driver->default_datatype,
5179                            r->default_datatype);
5180
5181         result = string_array_from_driver_info(mem_ctx,
5182                                                driver->dependent_files,
5183                                                &r->dependent_files,
5184                                                cservername,
5185                                                driver->architecture,
5186                                                driver->version);
5187         if (!W_ERROR_IS_OK(result)) {
5188                 return result;
5189         }
5190
5191         result = string_array_from_driver_info(mem_ctx,
5192                                                driver->previous_names,
5193                                                &r->previous_names,
5194                                                NULL, NULL, 0);
5195         if (!W_ERROR_IS_OK(result)) {
5196                 return result;
5197         }
5198
5199         r->driver_date          = driver->driver_date;
5200         r->driver_version       = driver->driver_version;
5201
5202         FILL_DRIVER_STRING(mem_ctx,
5203                            driver->manufacturer_name,
5204                            r->manufacturer_name);
5205         FILL_DRIVER_STRING(mem_ctx,
5206                            driver->manufacturer_url,
5207                            r->manufacturer_url);
5208         FILL_DRIVER_STRING(mem_ctx,
5209                            driver->hardware_id,
5210                            r->hardware_id);
5211         FILL_DRIVER_STRING(mem_ctx,
5212                            driver->provider,
5213                            r->provider);
5214
5215         return WERR_OK;
5216 }
5217
5218 /********************************************************************
5219  * fill a spoolss_DriverInfo8 struct
5220  ********************************************************************/
5221
5222 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5223                                         struct spoolss_DriverInfo8 *r,
5224                                         const struct spoolss_DriverInfo8 *driver,
5225                                         const char *servername)
5226 {
5227         const char *cservername = canon_servername(servername);
5228         WERROR result;
5229
5230         r->version              = driver->version;
5231
5232         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5233         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5234         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5235         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5236
5237         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5238                                driver->architecture,
5239                                driver->version,
5240                                driver->driver_path,
5241                                r->driver_path);
5242
5243         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5244                                driver->architecture,
5245                                driver->version,
5246                                driver->data_file,
5247                                r->data_file);
5248
5249         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5250                                driver->architecture,
5251                                driver->version,
5252                                driver->config_file,
5253                                r->config_file);
5254
5255         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5256                                driver->architecture,
5257                                driver->version,
5258                                driver->help_file,
5259                                r->help_file);
5260
5261         FILL_DRIVER_STRING(mem_ctx,
5262                            driver->monitor_name,
5263                            r->monitor_name);
5264
5265         FILL_DRIVER_STRING(mem_ctx,
5266                            driver->default_datatype,
5267                            r->default_datatype);
5268
5269         result = string_array_from_driver_info(mem_ctx,
5270                                                driver->dependent_files,
5271                                                &r->dependent_files,
5272                                                cservername,
5273                                                driver->architecture,
5274                                                driver->version);
5275         if (!W_ERROR_IS_OK(result)) {
5276                 return result;
5277         }
5278
5279         result = string_array_from_driver_info(mem_ctx,
5280                                                driver->previous_names,
5281                                                &r->previous_names,
5282                                                NULL, NULL, 0);
5283         if (!W_ERROR_IS_OK(result)) {
5284                 return result;
5285         }
5286
5287         r->driver_date          = driver->driver_date;
5288         r->driver_version       = driver->driver_version;
5289
5290         FILL_DRIVER_STRING(mem_ctx,
5291                            driver->manufacturer_name,
5292                            r->manufacturer_name);
5293         FILL_DRIVER_STRING(mem_ctx,
5294                            driver->manufacturer_url,
5295                            r->manufacturer_url);
5296         FILL_DRIVER_STRING(mem_ctx,
5297                            driver->hardware_id,
5298                            r->hardware_id);
5299         FILL_DRIVER_STRING(mem_ctx,
5300                            driver->provider,
5301                            r->provider);
5302
5303         FILL_DRIVER_STRING(mem_ctx,
5304                            driver->print_processor,
5305                            r->print_processor);
5306         FILL_DRIVER_STRING(mem_ctx,
5307                            driver->vendor_setup,
5308                            r->vendor_setup);
5309
5310         result = string_array_from_driver_info(mem_ctx,
5311                                                driver->color_profiles,
5312                                                &r->color_profiles,
5313                                                NULL, NULL, 0);
5314         if (!W_ERROR_IS_OK(result)) {
5315                 return result;
5316         }
5317
5318         FILL_DRIVER_STRING(mem_ctx,
5319                            driver->inf_path,
5320                            r->inf_path);
5321
5322         r->printer_driver_attributes    = driver->printer_driver_attributes;
5323
5324         result = string_array_from_driver_info(mem_ctx,
5325                                                driver->core_driver_dependencies,
5326                                                &r->core_driver_dependencies,
5327                                                NULL, NULL, 0);
5328         if (!W_ERROR_IS_OK(result)) {
5329                 return result;
5330         }
5331
5332         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5333         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5334
5335         return WERR_OK;
5336 }
5337
5338 #if 0 /* disabled until marshalling issues are resolved - gd */
5339 /********************************************************************
5340  ********************************************************************/
5341
5342 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5343                                           struct spoolss_DriverFileInfo *r,
5344                                           const char *cservername,
5345                                           const char *file_name,
5346                                           enum spoolss_DriverFileType file_type,
5347                                           uint32_t file_version)
5348 {
5349         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5350                                           cservername, file_name);
5351         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5352         r->file_type    = file_type;
5353         r->file_version = file_version;
5354
5355         return WERR_OK;
5356 }
5357
5358 /********************************************************************
5359  ********************************************************************/
5360
5361 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5362                                                  const struct spoolss_DriverInfo8 *driver,
5363                                                  const char *cservername,
5364                                                  struct spoolss_DriverFileInfo **info_p,
5365                                                  uint32_t *count_p)
5366 {
5367         struct spoolss_DriverFileInfo *info = NULL;
5368         uint32_t count = 0;
5369         WERROR result;
5370         uint32_t i;
5371
5372         *info_p = NULL;
5373         *count_p = 0;
5374
5375         if (strlen(driver->driver_path)) {
5376                 info = talloc_realloc(mem_ctx, info,
5377                                             struct spoolss_DriverFileInfo,
5378                                             count + 1);
5379                 W_ERROR_HAVE_NO_MEMORY(info);
5380                 result = fill_spoolss_DriverFileInfo(info,
5381                                                      &info[count],
5382                                                      cservername,
5383                                                      driver->driver_path,
5384                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5385                                                      0);
5386                 W_ERROR_NOT_OK_RETURN(result);
5387                 count++;
5388         }
5389
5390         if (strlen(driver->config_file)) {
5391                 info = talloc_realloc(mem_ctx, info,
5392                                             struct spoolss_DriverFileInfo,
5393                                             count + 1);
5394                 W_ERROR_HAVE_NO_MEMORY(info);
5395                 result = fill_spoolss_DriverFileInfo(info,
5396                                                      &info[count],
5397                                                      cservername,
5398                                                      driver->config_file,
5399                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5400                                                      0);
5401                 W_ERROR_NOT_OK_RETURN(result);
5402                 count++;
5403         }
5404
5405         if (strlen(driver->data_file)) {
5406                 info = talloc_realloc(mem_ctx, info,
5407                                             struct spoolss_DriverFileInfo,
5408                                             count + 1);
5409                 W_ERROR_HAVE_NO_MEMORY(info);
5410                 result = fill_spoolss_DriverFileInfo(info,
5411                                                      &info[count],
5412                                                      cservername,
5413                                                      driver->data_file,
5414                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5415                                                      0);
5416                 W_ERROR_NOT_OK_RETURN(result);
5417                 count++;
5418         }
5419
5420         if (strlen(driver->help_file)) {
5421                 info = talloc_realloc(mem_ctx, info,
5422                                             struct spoolss_DriverFileInfo,
5423                                             count + 1);
5424                 W_ERROR_HAVE_NO_MEMORY(info);
5425                 result = fill_spoolss_DriverFileInfo(info,
5426                                                      &info[count],
5427                                                      cservername,
5428                                                      driver->help_file,
5429                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5430                                                      0);
5431                 W_ERROR_NOT_OK_RETURN(result);
5432                 count++;
5433         }
5434
5435         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5436                 info = talloc_realloc(mem_ctx, info,
5437                                             struct spoolss_DriverFileInfo,
5438                                             count + 1);
5439                 W_ERROR_HAVE_NO_MEMORY(info);
5440                 result = fill_spoolss_DriverFileInfo(info,
5441                                                      &info[count],
5442                                                      cservername,
5443                                                      driver->dependent_files[i],
5444                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5445                                                      0);
5446                 W_ERROR_NOT_OK_RETURN(result);
5447                 count++;
5448         }
5449
5450         *info_p = info;
5451         *count_p = count;
5452
5453         return WERR_OK;
5454 }
5455
5456 /********************************************************************
5457  * fill a spoolss_DriverInfo101 struct
5458  ********************************************************************/
5459
5460 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5461                                           struct spoolss_DriverInfo101 *r,
5462                                           const struct spoolss_DriverInfo8 *driver,
5463                                           const char *servername)
5464 {
5465         const char *cservername = canon_servername(servername);
5466         WERROR result;
5467
5468         r->version              = driver->version;
5469
5470         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5471         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5472         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5473         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5474
5475         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5476                                                     cservername,
5477                                                     &r->file_info,
5478                                                     &r->file_count);
5479         if (!W_ERROR_IS_OK(result)) {
5480                 return result;
5481         }
5482
5483         FILL_DRIVER_STRING(mem_ctx,
5484                            driver->monitor_name,
5485                            r->monitor_name);
5486
5487         FILL_DRIVER_STRING(mem_ctx,
5488                            driver->default_datatype,
5489                            r->default_datatype);
5490
5491         result = string_array_from_driver_info(mem_ctx,
5492                                                driver->previous_names,
5493                                                &r->previous_names,
5494                                                NULL, NULL, 0);
5495         if (!W_ERROR_IS_OK(result)) {
5496                 return result;
5497         }
5498
5499         r->driver_date          = driver->driver_date;
5500         r->driver_version       = driver->driver_version;
5501
5502         FILL_DRIVER_STRING(mem_ctx,
5503                            driver->manufacturer_name,
5504                            r->manufacturer_name);
5505         FILL_DRIVER_STRING(mem_ctx,
5506                            driver->manufacturer_url,
5507                            r->manufacturer_url);
5508         FILL_DRIVER_STRING(mem_ctx,
5509                            driver->hardware_id,
5510                            r->hardware_id);
5511         FILL_DRIVER_STRING(mem_ctx,
5512                            driver->provider,
5513                            r->provider);
5514
5515         return WERR_OK;
5516 }
5517 #endif
5518 /********************************************************************
5519  ********************************************************************/
5520
5521 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5522                                                   const struct auth_session_info *session_info,
5523                                                   struct messaging_context *msg_ctx,
5524                                                   uint32_t level,
5525                                                   union spoolss_DriverInfo *r,
5526                                                   int snum,
5527                                                   const char *servername,
5528                                                   const char *architecture,
5529                                                   uint32_t version)
5530 {
5531         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5532         struct spoolss_DriverInfo8 *driver;
5533         WERROR result;
5534         struct dcerpc_binding_handle *b;
5535         TALLOC_CTX *tmp_ctx = NULL;
5536
5537         if (level == 101) {
5538                 return WERR_UNKNOWN_LEVEL;
5539         }
5540
5541         tmp_ctx = talloc_new(mem_ctx);
5542         if (!tmp_ctx) {
5543                 return WERR_NOMEM;
5544         }
5545
5546         result = winreg_printer_binding_handle(tmp_ctx,
5547                                                session_info,
5548                                                msg_ctx,
5549                                                &b);
5550         if (!W_ERROR_IS_OK(result)) {
5551                 goto done;
5552         }
5553
5554         result = winreg_get_printer(tmp_ctx, b,
5555                                     lp_const_servicename(snum),
5556                                     &pinfo2);
5557
5558         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5559                 win_errstr(result)));
5560
5561         if (!W_ERROR_IS_OK(result)) {
5562                 result = WERR_INVALID_PRINTER_NAME;
5563                 goto done;
5564         }
5565
5566         result = winreg_get_driver(tmp_ctx, b,
5567                                    architecture,
5568                                    pinfo2->drivername, version, &driver);
5569
5570         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5571                 win_errstr(result)));
5572
5573         if (!W_ERROR_IS_OK(result)) {
5574                 /*
5575                  * Is this a W2k client ?
5576                  */
5577
5578                 if (version < 3) {
5579                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5580                         goto done;
5581                 }
5582
5583                 /* Yes - try again with a WinNT driver. */
5584                 version = 2;
5585                 result = winreg_get_driver(tmp_ctx, b,
5586                                            architecture,
5587                                            pinfo2->drivername,
5588                                            version, &driver);
5589                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5590                         win_errstr(result)));
5591                 if (!W_ERROR_IS_OK(result)) {
5592                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5593                         goto done;
5594                 }
5595         }
5596
5597         /* these are allocated on mem_ctx and not tmp_ctx because they are
5598          * the 'return value' and need to utlive this call */
5599         switch (level) {
5600         case 1:
5601                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5602                 break;
5603         case 2:
5604                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5605                 break;
5606         case 3:
5607                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5608                 break;
5609         case 4:
5610                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5611                 break;
5612         case 5:
5613                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5614                 break;
5615         case 6:
5616                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5617                 break;
5618         case 8:
5619                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5620                 break;
5621 #if 0 /* disabled until marshalling issues are resolved - gd */
5622         case 101:
5623                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5624                 break;
5625 #endif
5626         default:
5627                 result = WERR_UNKNOWN_LEVEL;
5628                 break;
5629         }
5630
5631 done:
5632         talloc_free(tmp_ctx);
5633         return result;
5634 }
5635
5636 /****************************************************************
5637  _spoolss_GetPrinterDriver2
5638 ****************************************************************/
5639
5640 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5641                                   struct spoolss_GetPrinterDriver2 *r)
5642 {
5643         struct printer_handle *printer;
5644         WERROR result;
5645         uint32_t version = r->in.client_major_version;
5646
5647         int snum;
5648
5649         /* that's an [in out] buffer */
5650
5651         if (!r->in.buffer && (r->in.offered != 0)) {
5652                 return WERR_INVALID_PARAM;
5653         }
5654
5655         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5656
5657         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5658                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5659                 return WERR_INVALID_PRINTER_NAME;
5660         }
5661
5662         *r->out.needed = 0;
5663         *r->out.server_major_version = 0;
5664         *r->out.server_minor_version = 0;
5665
5666         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5667                 return WERR_BADFID;
5668         }
5669
5670         if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5671                 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5672                         "downgrading to v3\n"));
5673                 version = SPOOLSS_DRIVER_VERSION_200X;
5674         }
5675
5676         result = construct_printer_driver_info_level(p->mem_ctx,
5677                                                      get_session_info_system(),
5678                                                      p->msg_ctx,
5679                                                      r->in.level, r->out.info,
5680                                                      snum, printer->servername,
5681                                                      r->in.architecture,
5682                                                      version);
5683         if (!W_ERROR_IS_OK(result)) {
5684                 TALLOC_FREE(r->out.info);
5685                 return result;
5686         }
5687
5688         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5689                                                r->out.info, r->in.level);
5690         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5691
5692         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5693 }
5694
5695
5696 /****************************************************************
5697  _spoolss_StartPagePrinter
5698 ****************************************************************/
5699
5700 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5701                                  struct spoolss_StartPagePrinter *r)
5702 {
5703         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5704
5705         if (!Printer) {
5706                 DEBUG(3,("_spoolss_StartPagePrinter: "
5707                         "Error in startpageprinter printer handle\n"));
5708                 return WERR_BADFID;
5709         }
5710
5711         Printer->page_started = true;
5712         return WERR_OK;
5713 }
5714
5715 /****************************************************************
5716  _spoolss_EndPagePrinter
5717 ****************************************************************/
5718
5719 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5720                                struct spoolss_EndPagePrinter *r)
5721 {
5722         int snum;
5723
5724         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5725
5726         if (!Printer) {
5727                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5728                         OUR_HANDLE(r->in.handle)));
5729                 return WERR_BADFID;
5730         }
5731
5732         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5733                 return WERR_BADFID;
5734
5735         Printer->page_started = false;
5736         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5737
5738         return WERR_OK;
5739 }
5740
5741 /****************************************************************
5742  _spoolss_StartDocPrinter
5743 ****************************************************************/
5744
5745 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5746                                 struct spoolss_StartDocPrinter *r)
5747 {
5748         struct spoolss_DocumentInfo1 *info_1;
5749         int snum;
5750         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5751         WERROR werr;
5752         char *rhost;
5753         int rc;
5754
5755         if (!Printer) {
5756                 DEBUG(2,("_spoolss_StartDocPrinter: "
5757                         "Invalid handle (%s:%u:%u)\n",
5758                         OUR_HANDLE(r->in.handle)));
5759                 return WERR_BADFID;
5760         }
5761
5762         if (Printer->jobid) {
5763                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5764                           "StartDocPrinter called twice! "
5765                           "(existing jobid = %d)\n", Printer->jobid));
5766                 return WERR_INVALID_HANDLE;
5767         }
5768
5769         if (r->in.info_ctr->level != 1) {
5770                 return WERR_UNKNOWN_LEVEL;
5771         }
5772
5773         info_1 = r->in.info_ctr->info.info1;
5774
5775         /*
5776          * a nice thing with NT is it doesn't listen to what you tell it.
5777          * when asked to send _only_ RAW datas, it tries to send datas
5778          * in EMF format.
5779          *
5780          * So I add checks like in NT Server ...
5781          */
5782
5783         if (info_1->datatype) {
5784                 if (strcmp(info_1->datatype, "RAW") != 0) {
5785                         *r->out.job_id = 0;
5786                         return WERR_INVALID_DATATYPE;
5787                 }
5788         }
5789
5790         /* get the share number of the printer */
5791         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5792                 return WERR_BADFID;
5793         }
5794
5795         rc = get_remote_hostname(p->remote_address,
5796                                  &rhost,
5797                                  p->mem_ctx);
5798         if (rc < 0) {
5799                 return WERR_NOMEM;
5800         }
5801         if (strequal(rhost,"UNKNOWN")) {
5802                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5803                                                          p->mem_ctx);
5804                 if (rhost == NULL) {
5805                         return WERR_NOMEM;
5806                 }
5807         }
5808
5809         werr = print_job_start(p->session_info,
5810                                p->msg_ctx,
5811                                rhost,
5812                                snum,
5813                                info_1->document_name,
5814                                info_1->output_file,
5815                                Printer->devmode,
5816                                &Printer->jobid);
5817
5818         /* An error occured in print_job_start() so return an appropriate
5819            NT error code. */
5820
5821         if (!W_ERROR_IS_OK(werr)) {
5822                 return werr;
5823         }
5824
5825         Printer->document_started = true;
5826         *r->out.job_id = Printer->jobid;
5827
5828         return WERR_OK;
5829 }
5830
5831 /****************************************************************
5832  _spoolss_EndDocPrinter
5833 ****************************************************************/
5834
5835 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5836                               struct spoolss_EndDocPrinter *r)
5837 {
5838         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5839         NTSTATUS status;
5840         int snum;
5841
5842         if (!Printer) {
5843                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5844                         OUR_HANDLE(r->in.handle)));
5845                 return WERR_BADFID;
5846         }
5847
5848         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5849                 return WERR_BADFID;
5850         }
5851
5852         Printer->document_started = false;
5853         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5854         if (!NT_STATUS_IS_OK(status)) {
5855                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5856                           "print_job_end failed [%s]\n",
5857                           nt_errstr(status)));
5858         }
5859
5860         Printer->jobid = 0;
5861         return ntstatus_to_werror(status);
5862 }
5863
5864 /****************************************************************
5865  _spoolss_WritePrinter
5866 ****************************************************************/
5867
5868 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5869                              struct spoolss_WritePrinter *r)
5870 {
5871         ssize_t buffer_written;
5872         int snum;
5873         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5874
5875         if (!Printer) {
5876                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5877                         OUR_HANDLE(r->in.handle)));
5878                 *r->out.num_written = r->in._data_size;
5879                 return WERR_BADFID;
5880         }
5881
5882         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5883                 return WERR_BADFID;
5884
5885         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5886         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5887                                                    snum, Printer->jobid,
5888                                                    (const char *)r->in.data.data,
5889                                                    (size_t)r->in._data_size);
5890         if (buffer_written == (ssize_t)-1) {
5891                 *r->out.num_written = 0;
5892                 if (errno == ENOSPC)
5893                         return WERR_NO_SPOOL_SPACE;
5894                 else
5895                         return WERR_ACCESS_DENIED;
5896         }
5897
5898         *r->out.num_written = r->in._data_size;
5899
5900         return WERR_OK;
5901 }
5902
5903 /********************************************************************
5904  * api_spoolss_getprinter
5905  * called from the spoolss dispatcher
5906  *
5907  ********************************************************************/
5908
5909 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5910                               struct pipes_struct *p)
5911 {
5912         const struct auth_session_info *session_info = p->session_info;
5913         int snum;
5914         WERROR errcode = WERR_BADFUNC;
5915         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5916
5917         if (!Printer) {
5918                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5919                         OUR_HANDLE(handle)));
5920                 return WERR_BADFID;
5921         }
5922
5923         if (!get_printer_snum(p, handle, &snum, NULL))
5924                 return WERR_BADFID;
5925
5926         switch (command) {
5927         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5928                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5929                 break;
5930         case SPOOLSS_PRINTER_CONTROL_RESUME:
5931         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5932                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5933                 break;
5934         case SPOOLSS_PRINTER_CONTROL_PURGE:
5935                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5936                 break;
5937         default:
5938                 return WERR_UNKNOWN_LEVEL;
5939         }
5940
5941         return errcode;
5942 }
5943
5944
5945 /****************************************************************
5946  _spoolss_AbortPrinter
5947  * From MSDN: "Deletes printer's spool file if printer is configured
5948  * for spooling"
5949 ****************************************************************/
5950
5951 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5952                              struct spoolss_AbortPrinter *r)
5953 {
5954         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5955         int             snum;
5956         WERROR          errcode = WERR_OK;
5957
5958         if (!Printer) {
5959                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5960                         OUR_HANDLE(r->in.handle)));
5961                 return WERR_BADFID;
5962         }
5963
5964         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5965                 return WERR_BADFID;
5966
5967         if (!Printer->document_started) {
5968                 return WERR_SPL_NO_STARTDOC;
5969         }
5970
5971         errcode = print_job_delete(p->session_info,
5972                                    p->msg_ctx,
5973                                    snum,
5974                                    Printer->jobid);
5975
5976         return errcode;
5977 }
5978
5979 /********************************************************************
5980  * called by spoolss_api_setprinter
5981  * when updating a printer description
5982  ********************************************************************/
5983
5984 static WERROR update_printer_sec(struct policy_handle *handle,
5985                                  struct pipes_struct *p,
5986                                  struct sec_desc_buf *secdesc_ctr)
5987 {
5988         struct spoolss_security_descriptor *new_secdesc = NULL;
5989         struct spoolss_security_descriptor *old_secdesc = NULL;
5990         const char *printer;
5991         WERROR result;
5992         int snum;
5993         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5994         struct dcerpc_binding_handle *b;
5995         TALLOC_CTX *tmp_ctx = NULL;
5996
5997         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5998                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5999                          OUR_HANDLE(handle)));
6000
6001                 result = WERR_BADFID;
6002                 goto done;
6003         }
6004
6005         if (secdesc_ctr == NULL) {
6006                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6007                 result = WERR_INVALID_PARAM;
6008                 goto done;
6009         }
6010         printer = lp_const_servicename(snum);
6011
6012         /* Check the user has permissions to change the security
6013            descriptor.  By experimentation with two NT machines, the user
6014            requires Full Access to the printer to change security
6015            information. */
6016
6017         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6018                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6019                 result = WERR_ACCESS_DENIED;
6020                 goto done;
6021         }
6022
6023         tmp_ctx = talloc_new(p->mem_ctx);
6024         if (!tmp_ctx) {
6025                 return WERR_NOMEM;
6026         }
6027
6028         result = winreg_printer_binding_handle(tmp_ctx,
6029                                                get_session_info_system(),
6030                                                p->msg_ctx,
6031                                                &b);
6032         if (!W_ERROR_IS_OK(result)) {
6033                 goto done;
6034         }
6035
6036         /* NT seems to like setting the security descriptor even though
6037            nothing may have actually changed. */
6038         result = winreg_get_printer_secdesc(tmp_ctx, b,
6039                                             printer,
6040                                             &old_secdesc);
6041         if (!W_ERROR_IS_OK(result)) {
6042                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6043                 result = WERR_BADFID;
6044                 goto done;
6045         }
6046
6047         if (DEBUGLEVEL >= 10) {
6048                 struct security_acl *the_acl;
6049                 int i;
6050
6051                 the_acl = old_secdesc->dacl;
6052                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6053                            printer, the_acl->num_aces));
6054
6055                 for (i = 0; i < the_acl->num_aces; i++) {
6056                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6057                                            &the_acl->aces[i].trustee),
6058                                   the_acl->aces[i].access_mask));
6059                 }
6060
6061                 the_acl = secdesc_ctr->sd->dacl;
6062
6063                 if (the_acl) {
6064                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6065                                    printer, the_acl->num_aces));
6066
6067                         for (i = 0; i < the_acl->num_aces; i++) {
6068                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6069                                                    &the_acl->aces[i].trustee),
6070                                            the_acl->aces[i].access_mask));
6071                         }
6072                 } else {
6073                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6074                 }
6075         }
6076
6077         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6078         if (new_secdesc == NULL) {
6079                 result = WERR_NOMEM;
6080                 goto done;
6081         }
6082
6083         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6084                 result = WERR_OK;
6085                 goto done;
6086         }
6087
6088         result = winreg_set_printer_secdesc(tmp_ctx, b,
6089                                             printer,
6090                                             new_secdesc);
6091
6092 done:
6093         talloc_free(tmp_ctx);
6094         return result;
6095 }
6096
6097 /********************************************************************
6098  Canonicalize printer info from a client
6099  ********************************************************************/
6100
6101 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6102                              struct spoolss_SetPrinterInfo2 *info2,
6103                              int snum)
6104 {
6105         fstring printername;
6106         const char *p;
6107
6108         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6109                 "portname=%s drivername=%s comment=%s location=%s\n",
6110                 info2->servername, info2->printername, info2->sharename,
6111                 info2->portname, info2->drivername, info2->comment,
6112                 info2->location));
6113
6114         /* we force some elements to "correct" values */
6115         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6116         if (info2->servername == NULL) {
6117                 return false;
6118         }
6119         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6120         if (info2->sharename == NULL) {
6121                 return false;
6122         }
6123
6124         /* check to see if we allow printername != sharename */
6125         if (lp_force_printername(snum)) {
6126                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6127                                         lp_netbios_name(), info2->sharename);
6128         } else {
6129                 /* make sure printername is in \\server\printername format */
6130                 fstrcpy(printername, info2->printername);
6131                 p = printername;
6132                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6133                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6134                                 p++;
6135                 }
6136
6137                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6138                                         lp_netbios_name(), p);
6139         }
6140         if (info2->printername == NULL) {
6141                 return false;
6142         }
6143
6144         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6145         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6146
6147         return true;
6148 }
6149
6150 /****************************************************************************
6151 ****************************************************************************/
6152
6153 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6154 {
6155         char *cmd = lp_addport_cmd(talloc_tos());
6156         char *command = NULL;
6157         int ret;
6158         bool is_print_op = false;
6159
6160         if ( !*cmd ) {
6161                 return WERR_ACCESS_DENIED;
6162         }
6163
6164         command = talloc_asprintf(ctx,
6165                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6166         if (!command) {
6167                 return WERR_NOMEM;
6168         }
6169
6170         if ( token )
6171                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6172
6173         DEBUG(10,("Running [%s]\n", command));
6174
6175         /********* BEGIN SePrintOperatorPrivilege **********/
6176
6177         if ( is_print_op )
6178                 become_root();
6179
6180         ret = smbrun(command, NULL);
6181
6182         if ( is_print_op )
6183                 unbecome_root();
6184
6185         /********* END SePrintOperatorPrivilege **********/
6186
6187         DEBUGADD(10,("returned [%d]\n", ret));
6188
6189         TALLOC_FREE(command);
6190
6191         if ( ret != 0 ) {
6192                 return WERR_ACCESS_DENIED;
6193         }
6194
6195         return WERR_OK;
6196 }
6197
6198 /****************************************************************************
6199 ****************************************************************************/
6200
6201 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6202                                    int snum)
6203 {
6204         /*
6205          * As we do not know if we are embedded in the file server process
6206          * or not, we have to pretend that all shares are in use.
6207          */
6208         return true;
6209 }
6210
6211 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6212                              struct spoolss_SetPrinterInfo2 *info2,
6213                              const char *remote_machine,
6214                              struct messaging_context *msg_ctx)
6215 {
6216         char *cmd = lp_addprinter_cmd(talloc_tos());
6217         char **qlines;
6218         char *command = NULL;
6219         int numlines;
6220         int ret;
6221         int fd;
6222         bool is_print_op = false;
6223
6224         if (!remote_machine) {
6225                 return false;
6226         }
6227
6228         command = talloc_asprintf(ctx,
6229                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6230                         cmd, info2->printername, info2->sharename,
6231                         info2->portname, info2->drivername,
6232                         info2->location, info2->comment, remote_machine);
6233         if (!command) {
6234                 return false;
6235         }
6236
6237         if ( token )
6238                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6239
6240         DEBUG(10,("Running [%s]\n", command));
6241
6242         /********* BEGIN SePrintOperatorPrivilege **********/
6243
6244         if ( is_print_op )
6245                 become_root();
6246
6247         if ( (ret = smbrun(command, &fd)) == 0 ) {
6248                 /* Tell everyone we updated smb.conf. */
6249                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6250         }
6251
6252         if ( is_print_op )
6253                 unbecome_root();
6254
6255         /********* END SePrintOperatorPrivilege **********/
6256
6257         DEBUGADD(10,("returned [%d]\n", ret));
6258
6259         TALLOC_FREE(command);
6260
6261         if ( ret != 0 ) {
6262                 if (fd != -1)
6263                         close(fd);
6264                 return false;
6265         }
6266
6267         /* reload our services immediately */
6268         become_root();
6269         reload_services(NULL, spoolss_conn_snum_used, false);
6270         unbecome_root();
6271
6272         numlines = 0;
6273         /* Get lines and convert them back to dos-codepage */
6274         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6275         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6276         close(fd);
6277
6278         /* Set the portname to what the script says the portname should be. */
6279         /* but don't require anything to be return from the script exit a good error code */
6280
6281         if (numlines) {
6282                 /* Set the portname to what the script says the portname should be. */
6283                 info2->portname = talloc_strdup(ctx, qlines[0]);
6284                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6285         }
6286
6287         TALLOC_FREE(qlines);
6288         return true;
6289 }
6290
6291 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6292                                const struct auth_session_info *session_info,
6293                                struct messaging_context *msg_ctx,
6294                                int snum,
6295                                struct spoolss_SetPrinterInfo2 *printer,
6296                                struct spoolss_PrinterInfo2 *old_printer)
6297 {
6298         bool force_update = (old_printer == NULL);
6299         const char *dnsdomname;
6300         const char *longname;
6301         const char *uncname;
6302         const char *spooling;
6303         DATA_BLOB buffer;
6304         WERROR result = WERR_OK;
6305         struct dcerpc_binding_handle *b;
6306         TALLOC_CTX *tmp_ctx;
6307         bool ok;
6308
6309         tmp_ctx = talloc_new(mem_ctx);
6310         if (!tmp_ctx) {
6311                 return WERR_NOMEM;
6312         }
6313
6314         result = winreg_printer_binding_handle(tmp_ctx,
6315                                                session_info,
6316                                                msg_ctx,
6317                                                &b);
6318         if (!W_ERROR_IS_OK(result)) {
6319                 goto done;
6320         }
6321
6322         if (printer->drivername != NULL &&
6323             (force_update ||
6324              !strequal(printer->drivername, old_printer->drivername))) {
6325                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6326                 if (!ok) {
6327                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6328                         result = WERR_INVALID_DATA;
6329                         goto done;
6330                 }
6331                 result = winreg_set_printer_dataex(tmp_ctx, b,
6332                                           printer->sharename,
6333                                           SPOOL_DSSPOOLER_KEY,
6334                                           SPOOL_REG_DRIVERNAME,
6335                                           REG_SZ,
6336                                           buffer.data,
6337                                           buffer.length);
6338                 if (!W_ERROR_IS_OK(result)) {
6339                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6340                         goto done;
6341                 }
6342
6343                 if (!force_update) {
6344                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6345                                 printer->drivername));
6346
6347                         notify_printer_driver(server_event_context(), msg_ctx,
6348                                               snum, printer->drivername ?
6349                                               printer->drivername : "");
6350                 }
6351         }
6352
6353         if (printer->comment != NULL &&
6354             (force_update ||
6355              !strequal(printer->comment, old_printer->comment))) {
6356                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6357                 if (!ok) {
6358                         DEBUG(0, ("comment data corrupted\n"));
6359                         result = WERR_INVALID_DATA;
6360                         goto done;
6361                 }
6362                 result = winreg_set_printer_dataex(tmp_ctx, b,
6363                                           printer->sharename,
6364                                           SPOOL_DSSPOOLER_KEY,
6365                                           SPOOL_REG_DESCRIPTION,
6366                                           REG_SZ,
6367                                           buffer.data,
6368                                           buffer.length);
6369                 if (!W_ERROR_IS_OK(result)) {
6370                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6371                         goto done;
6372                 }
6373
6374                 if (!force_update) {
6375                         notify_printer_comment(server_event_context(), msg_ctx,
6376                                                snum, printer->comment ?
6377                                                printer->comment : "");
6378                 }
6379         }
6380
6381         if (printer->sharename != NULL &&
6382             (force_update ||
6383              !strequal(printer->sharename, old_printer->sharename))) {
6384                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6385                 if (!ok) {
6386                         DEBUG(0, ("sharename data corrupted\n"));
6387                         result = WERR_INVALID_DATA;
6388                         goto done;
6389                 }
6390                 result = winreg_set_printer_dataex(tmp_ctx, b,
6391                                           printer->sharename,
6392                                           SPOOL_DSSPOOLER_KEY,
6393                                           SPOOL_REG_PRINTSHARENAME,
6394                                           REG_SZ,
6395                                           buffer.data,
6396                                           buffer.length);
6397                 if (!W_ERROR_IS_OK(result)) {
6398                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6399                         goto done;
6400                 }
6401
6402                 if (!force_update) {
6403                         notify_printer_sharename(server_event_context(),
6404                                                  msg_ctx,
6405                                                  snum, printer->sharename ?
6406                                                  printer->sharename : "");
6407                 }
6408         }
6409
6410         if (printer->printername != NULL &&
6411             (force_update ||
6412              !strequal(printer->printername, old_printer->printername))) {
6413                 const char *p;
6414
6415                 p = strrchr(printer->printername, '\\' );
6416                 if (p != NULL) {
6417                         p++;
6418                 } else {
6419                         p = printer->printername;
6420                 }
6421
6422                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6423                 if (!ok) {
6424                         DEBUG(0, ("printername data corrupted\n"));
6425                         result = WERR_INVALID_DATA;
6426                         goto done;
6427                 }
6428                 result = winreg_set_printer_dataex(tmp_ctx, b,
6429                                           printer->sharename,
6430                                           SPOOL_DSSPOOLER_KEY,
6431                                           SPOOL_REG_PRINTERNAME,
6432                                           REG_SZ,
6433                                           buffer.data,
6434                                           buffer.length);
6435                 if (!W_ERROR_IS_OK(result)) {
6436                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6437                         goto done;
6438                 }
6439
6440                 if (!force_update) {
6441                         notify_printer_printername(server_event_context(),
6442                                                    msg_ctx, snum, p ? p : "");
6443                 }
6444         }
6445
6446         if (printer->portname != NULL &&
6447             (force_update ||
6448              !strequal(printer->portname, old_printer->portname))) {
6449                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6450                 if (!ok) {
6451                         DEBUG(0, ("portname data corrupted\n"));
6452                         result = WERR_INVALID_DATA;
6453                         goto done;
6454                 }
6455                 result = winreg_set_printer_dataex(tmp_ctx, b,
6456                                           printer->sharename,
6457                                           SPOOL_DSSPOOLER_KEY,
6458                                           SPOOL_REG_PORTNAME,
6459                                           REG_SZ,
6460                                           buffer.data,
6461                                           buffer.length);
6462                 if (!W_ERROR_IS_OK(result)) {
6463                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6464                         goto done;
6465                 }
6466
6467                 if (!force_update) {
6468                         notify_printer_port(server_event_context(),
6469                                             msg_ctx, snum, printer->portname ?
6470                                             printer->portname : "");
6471                 }
6472         }
6473
6474         if (printer->location != NULL &&
6475             (force_update ||
6476              !strequal(printer->location, old_printer->location))) {
6477                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6478                 if (!ok) {
6479                         DEBUG(0, ("location data corrupted\n"));
6480                         result = WERR_INVALID_DATA;
6481                         goto done;
6482                 }
6483                 result = winreg_set_printer_dataex(tmp_ctx, b,
6484                                           printer->sharename,
6485                                           SPOOL_DSSPOOLER_KEY,
6486                                           SPOOL_REG_LOCATION,
6487                                           REG_SZ,
6488                                           buffer.data,
6489                                           buffer.length);
6490                 if (!W_ERROR_IS_OK(result)) {
6491                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6492                         goto done;
6493                 }
6494
6495                 if (!force_update) {
6496                         notify_printer_location(server_event_context(),
6497                                                 msg_ctx, snum,
6498                                                 printer->location ?
6499                                                 printer->location : "");
6500                 }
6501         }
6502
6503         if (printer->sepfile != NULL &&
6504             (force_update ||
6505              !strequal(printer->sepfile, old_printer->sepfile))) {
6506                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6507                 if (!ok) {
6508                         DEBUG(0, ("sepfile data corrupted\n"));
6509                         result = WERR_INVALID_DATA;
6510                         goto done;
6511                 }
6512                 result = winreg_set_printer_dataex(tmp_ctx, b,
6513                                           printer->sharename,
6514                                           SPOOL_DSSPOOLER_KEY,
6515                                           SPOOL_REG_PRINTSEPARATORFILE,
6516                                           REG_SZ,
6517                                           buffer.data,
6518                                           buffer.length);
6519                 if (!W_ERROR_IS_OK(result)) {
6520                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6521                         goto done;
6522                 }
6523
6524                 if (!force_update) {
6525                         notify_printer_sepfile(server_event_context(),
6526                                                msg_ctx, snum,
6527                                                printer->sepfile ?
6528                                                printer->sepfile : "");
6529                 }
6530         }
6531
6532         if (printer->starttime != 0 &&
6533             (force_update ||
6534              printer->starttime != old_printer->starttime)) {
6535                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6536                 SIVAL(buffer.data, 0, printer->starttime);
6537                 result = winreg_set_printer_dataex(tmp_ctx, b,
6538                                           printer->sharename,
6539                                           SPOOL_DSSPOOLER_KEY,
6540                                           SPOOL_REG_PRINTSTARTTIME,
6541                                           REG_DWORD,
6542                                           buffer.data,
6543                                           buffer.length);
6544                 if (!W_ERROR_IS_OK(result)) {
6545                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6546                         goto done;
6547                 }
6548         }
6549
6550         if (printer->untiltime != 0 &&
6551             (force_update ||
6552              printer->untiltime != old_printer->untiltime)) {
6553                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6554                 SIVAL(buffer.data, 0, printer->untiltime);
6555                 result = winreg_set_printer_dataex(tmp_ctx, b,
6556                                           printer->sharename,
6557                                           SPOOL_DSSPOOLER_KEY,
6558                                           SPOOL_REG_PRINTENDTIME,
6559                                           REG_DWORD,
6560                                           buffer.data,
6561                                           buffer.length);
6562                 if (!W_ERROR_IS_OK(result)) {
6563                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6564                         goto done;
6565                 }
6566         }
6567
6568         if (force_update || printer->priority != old_printer->priority) {
6569                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6570                 SIVAL(buffer.data, 0, printer->priority);
6571                 result = winreg_set_printer_dataex(tmp_ctx, b,
6572                                           printer->sharename,
6573                                           SPOOL_DSSPOOLER_KEY,
6574                                           SPOOL_REG_PRIORITY,
6575                                           REG_DWORD,
6576                                           buffer.data,
6577                                           buffer.length);
6578                 if (!W_ERROR_IS_OK(result)) {
6579                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6580                         goto done;
6581                 }
6582         }
6583
6584         if (force_update || printer->attributes != old_printer->attributes) {
6585                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6586                 SIVAL(buffer.data, 0, (printer->attributes &
6587                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6588                 result = winreg_set_printer_dataex(tmp_ctx, b,
6589                                           printer->sharename,
6590                                           SPOOL_DSSPOOLER_KEY,
6591                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6592                                           REG_DWORD,
6593                                           buffer.data,
6594                                           buffer.length);
6595                 if (!W_ERROR_IS_OK(result)) {
6596                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6597                         goto done;
6598                 }
6599
6600                 switch (printer->attributes & 0x3) {
6601                         case 0:
6602                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6603                                 break;
6604                         case 1:
6605                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6606                                 break;
6607                         case 2:
6608                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6609                                 break;
6610                         default:
6611                                 spooling = "unknown";
6612                 }
6613                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6614                 if (!ok) {
6615                         DEBUG(0, ("printSpooling data corrupted\n"));
6616                         result = WERR_INVALID_DATA;
6617                         goto done;
6618                 }
6619                 winreg_set_printer_dataex(tmp_ctx, b,
6620                                           printer->sharename,
6621                                           SPOOL_DSSPOOLER_KEY,
6622                                           SPOOL_REG_PRINTSPOOLING,
6623                                           REG_SZ,
6624                                           buffer.data,
6625                                           buffer.length);
6626         }
6627
6628         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6629         if (!ok) {
6630                 DEBUG(0, ("shortServerName data corrupted\n"));
6631                 result = WERR_INVALID_DATA;
6632                 goto done;
6633         }
6634         result = winreg_set_printer_dataex(tmp_ctx, b,
6635                                   printer->sharename,
6636                                   SPOOL_DSSPOOLER_KEY,
6637                                   SPOOL_REG_SHORTSERVERNAME,
6638                                   REG_SZ,
6639                                   buffer.data,
6640                                   buffer.length);
6641         if (!W_ERROR_IS_OK(result)) {
6642                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6643                 goto done;
6644         }
6645
6646         dnsdomname = get_mydnsfullname();
6647         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6648                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6649         } else {
6650                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6651         }
6652         if (longname == NULL) {
6653                 result = WERR_NOMEM;
6654                 goto done;
6655         }
6656
6657         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6658         if (!ok) {
6659                 DEBUG(0, ("longname data corrupted\n"));
6660                 result = WERR_INVALID_DATA;
6661                 goto done;
6662         }
6663         result = winreg_set_printer_dataex(tmp_ctx, b,
6664                                            printer->sharename,
6665                                            SPOOL_DSSPOOLER_KEY,
6666                                            SPOOL_REG_SERVERNAME,
6667                                            REG_SZ,
6668                                            buffer.data,
6669                                            buffer.length);
6670         if (!W_ERROR_IS_OK(result)) {
6671                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6672                 goto done;
6673         }
6674
6675         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6676                                   lp_netbios_name(), printer->sharename);
6677         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6678         if (!ok) {
6679                 DEBUG(0, ("uncName data corrupted\n"));
6680                 result = WERR_INVALID_DATA;
6681                 goto done;
6682         }
6683         result = winreg_set_printer_dataex(tmp_ctx, b,
6684                                   printer->sharename,
6685                                   SPOOL_DSSPOOLER_KEY,
6686                                   SPOOL_REG_UNCNAME,
6687                                   REG_SZ,
6688                                   buffer.data,
6689                                   buffer.length);
6690         if (!W_ERROR_IS_OK(result)) {
6691                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6692                 goto done;
6693         }
6694
6695 done:
6696         talloc_free(tmp_ctx);
6697         return result;
6698 }
6699
6700 /********************************************************************
6701  * Called by spoolss_api_setprinter
6702  * when updating a printer description.
6703  ********************************************************************/
6704
6705 static WERROR update_printer(struct pipes_struct *p,
6706                              struct policy_handle *handle,
6707                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6708                              struct spoolss_DeviceMode *devmode)
6709 {
6710         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6711         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6712         struct spoolss_PrinterInfo2 *old_printer;
6713         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6714         int snum;
6715         WERROR result = WERR_OK;
6716         TALLOC_CTX *tmp_ctx;
6717         struct dcerpc_binding_handle *b;
6718
6719         DEBUG(8,("update_printer\n"));
6720
6721         tmp_ctx = talloc_new(p->mem_ctx);
6722         if (tmp_ctx == NULL) {
6723                 return WERR_NOMEM;
6724         }
6725
6726         if (!Printer) {
6727                 result = WERR_BADFID;
6728                 goto done;
6729         }
6730
6731         if (!get_printer_snum(p, handle, &snum, NULL)) {
6732                 result = WERR_BADFID;
6733                 goto done;
6734         }
6735
6736         result = winreg_printer_binding_handle(tmp_ctx,
6737                                                get_session_info_system(),
6738                                                p->msg_ctx,
6739                                                &b);
6740         if (!W_ERROR_IS_OK(result)) {
6741                 goto done;
6742         }
6743
6744         result = winreg_get_printer(tmp_ctx, b,
6745                                     lp_const_servicename(snum),
6746                                     &old_printer);
6747         if (!W_ERROR_IS_OK(result)) {
6748                 result = WERR_BADFID;
6749                 goto done;
6750         }
6751
6752         /* Do sanity check on the requested changes for Samba */
6753         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6754                 result = WERR_INVALID_PARAM;
6755                 goto done;
6756         }
6757
6758         /* FIXME!!! If the driver has changed we really should verify that
6759            it is installed before doing much else   --jerry */
6760
6761         /* Check calling user has permission to update printer description */
6762         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6763                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6764                 result = WERR_ACCESS_DENIED;
6765                 goto done;
6766         }
6767
6768         /* Call addprinter hook */
6769         /* Check changes to see if this is really needed */
6770
6771         if (*lp_addprinter_cmd(talloc_tos()) &&
6772                         (!strequal(printer->drivername, old_printer->drivername) ||
6773                          !strequal(printer->comment, old_printer->comment) ||
6774                          !strequal(printer->portname, old_printer->portname) ||
6775                          !strequal(printer->location, old_printer->location)) )
6776         {
6777                 char *raddr;
6778
6779                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6780                                                          p->mem_ctx);
6781                 if (raddr == NULL) {
6782                         return WERR_NOMEM;
6783                 }
6784
6785                 /* add_printer_hook() will call reload_services() */
6786                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6787                                       printer, raddr,
6788                                       p->msg_ctx)) {
6789                         result = WERR_ACCESS_DENIED;
6790                         goto done;
6791                 }
6792         }
6793
6794         result = update_dsspooler(tmp_ctx,
6795                                   get_session_info_system(),
6796                                   p->msg_ctx,
6797                                   snum,
6798                                   printer,
6799                                   old_printer);
6800         if (!W_ERROR_IS_OK(result)) {
6801                 goto done;
6802         }
6803
6804         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6805
6806         if (devmode == NULL) {
6807                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6808         }
6809         result = winreg_update_printer(tmp_ctx, b,
6810                                        printer->sharename,
6811                                        printer_mask,
6812                                        printer,
6813                                        devmode,
6814                                        NULL);
6815
6816 done:
6817         talloc_free(tmp_ctx);
6818
6819         return result;
6820 }
6821
6822 /****************************************************************************
6823 ****************************************************************************/
6824 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6825                                            struct policy_handle *handle,
6826                                            struct spoolss_SetPrinterInfo7 *info7)
6827 {
6828 #ifdef HAVE_ADS
6829         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6830         WERROR result;
6831         int snum;
6832         struct printer_handle *Printer;
6833
6834         if ( lp_security() != SEC_ADS ) {
6835                 return WERR_UNKNOWN_LEVEL;
6836         }
6837
6838         Printer = find_printer_index_by_hnd(p, handle);
6839
6840         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6841
6842         if (!Printer)
6843                 return WERR_BADFID;
6844
6845         if (!get_printer_snum(p, handle, &snum, NULL))
6846                 return WERR_BADFID;
6847
6848         result = winreg_get_printer_internal(p->mem_ctx,
6849                                     get_session_info_system(),
6850                                     p->msg_ctx,
6851                                     lp_servicename(talloc_tos(), snum),
6852                                     &pinfo2);
6853         if (!W_ERROR_IS_OK(result)) {
6854                 return WERR_BADFID;
6855         }
6856
6857         nt_printer_publish(pinfo2,
6858                            get_session_info_system(),
6859                            p->msg_ctx,
6860                            pinfo2,
6861                            info7->action);
6862
6863         TALLOC_FREE(pinfo2);
6864         return WERR_OK;
6865 #else
6866         return WERR_UNKNOWN_LEVEL;
6867 #endif
6868 }
6869
6870 /********************************************************************
6871  ********************************************************************/
6872
6873 static WERROR update_printer_devmode(struct pipes_struct *p,
6874                                      struct policy_handle *handle,
6875                                      struct spoolss_DeviceMode *devmode)
6876 {
6877         int snum;
6878         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6879         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6880
6881         DEBUG(8,("update_printer_devmode\n"));
6882
6883         if (!Printer) {
6884                 return WERR_BADFID;
6885         }
6886
6887         if (!get_printer_snum(p, handle, &snum, NULL)) {
6888                 return WERR_BADFID;
6889         }
6890
6891         /* Check calling user has permission to update printer description */
6892         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6893                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6894                 return WERR_ACCESS_DENIED;
6895         }
6896
6897         return winreg_update_printer_internal(p->mem_ctx,
6898                                      get_session_info_system(),
6899                                      p->msg_ctx,
6900                                      lp_const_servicename(snum),
6901                                      info2_mask,
6902                                      NULL,
6903                                      devmode,
6904                                      NULL);
6905 }
6906
6907
6908 /****************************************************************
6909  _spoolss_SetPrinter
6910 ****************************************************************/
6911
6912 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6913                            struct spoolss_SetPrinter *r)
6914 {
6915         WERROR result;
6916
6917         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6918
6919         if (!Printer) {
6920                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6921                         OUR_HANDLE(r->in.handle)));
6922                 return WERR_BADFID;
6923         }
6924
6925         /* check the level */
6926         switch (r->in.info_ctr->level) {
6927                 case 0:
6928                         return control_printer(r->in.handle, r->in.command, p);
6929                 case 2:
6930                         result = update_printer(p, r->in.handle,
6931                                                 r->in.info_ctr,
6932                                                 r->in.devmode_ctr->devmode);
6933                         if (!W_ERROR_IS_OK(result))
6934                                 return result;
6935                         if (r->in.secdesc_ctr->sd)
6936                                 result = update_printer_sec(r->in.handle, p,
6937                                                             r->in.secdesc_ctr);
6938                         return result;
6939                 case 3:
6940                         return update_printer_sec(r->in.handle, p,
6941                                                   r->in.secdesc_ctr);
6942                 case 7:
6943                         return publish_or_unpublish_printer(p, r->in.handle,
6944                                                             r->in.info_ctr->info.info7);
6945                 case 8:
6946                         return update_printer_devmode(p, r->in.handle,
6947                                                       r->in.devmode_ctr->devmode);
6948                 default:
6949                         return WERR_UNKNOWN_LEVEL;
6950         }
6951 }
6952
6953 /****************************************************************
6954  _spoolss_FindClosePrinterNotify
6955 ****************************************************************/
6956
6957 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6958                                        struct spoolss_FindClosePrinterNotify *r)
6959 {
6960         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6961
6962         if (!Printer) {
6963                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6964                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6965                 return WERR_BADFID;
6966         }
6967
6968         if (Printer->notify.cli_chan != NULL &&
6969             Printer->notify.cli_chan->active_connections > 0) {
6970                 int snum = -1;
6971
6972                 if (Printer->printer_type == SPLHND_PRINTER) {
6973                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6974                                 return WERR_BADFID;
6975                         }
6976                 }
6977
6978                 srv_spoolss_replycloseprinter(snum, Printer);
6979         }
6980
6981         Printer->notify.flags=0;
6982         Printer->notify.options=0;
6983         Printer->notify.localmachine[0]='\0';
6984         Printer->notify.printerlocal=0;
6985         TALLOC_FREE(Printer->notify.option);
6986
6987         return WERR_OK;
6988 }
6989
6990 /****************************************************************
6991  _spoolss_AddJob
6992 ****************************************************************/
6993
6994 WERROR _spoolss_AddJob(struct pipes_struct *p,
6995                        struct spoolss_AddJob *r)
6996 {
6997         if (!r->in.buffer && (r->in.offered != 0)) {
6998                 return WERR_INVALID_PARAM;
6999         }
7000
7001         /* this is what a NT server returns for AddJob. AddJob must fail on
7002          * non-local printers */
7003
7004         if (r->in.level != 1) {
7005                 return WERR_UNKNOWN_LEVEL;
7006         }
7007
7008         return WERR_INVALID_PARAM;
7009 }
7010
7011 /****************************************************************************
7012 fill_job_info1
7013 ****************************************************************************/
7014
7015 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7016                              struct spoolss_JobInfo1 *r,
7017                              const print_queue_struct *queue,
7018                              int position, int snum,
7019                              struct spoolss_PrinterInfo2 *pinfo2)
7020 {
7021         struct tm *t;
7022
7023         t = gmtime(&queue->time);
7024
7025         r->job_id               = queue->sysjob;
7026
7027         r->printer_name         = lp_servicename(mem_ctx, snum);
7028         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7029         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7030         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7031         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7032         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7033         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7034         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7035         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7036         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7037         r->text_status          = talloc_strdup(mem_ctx, "");
7038         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7039
7040         r->status               = nt_printj_status(queue->status);
7041         r->priority             = queue->priority;
7042         r->position             = position;
7043         r->total_pages          = queue->page_count;
7044         r->pages_printed        = 0; /* ??? */
7045
7046         init_systemtime(&r->submitted, t);
7047
7048         return WERR_OK;
7049 }
7050
7051 /****************************************************************************
7052 fill_job_info2
7053 ****************************************************************************/
7054
7055 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7056                              struct spoolss_JobInfo2 *r,
7057                              const print_queue_struct *queue,
7058                              int position, int snum,
7059                              struct spoolss_PrinterInfo2 *pinfo2,
7060                              struct spoolss_DeviceMode *devmode)
7061 {
7062         struct tm *t;
7063
7064         t = gmtime(&queue->time);
7065
7066         r->job_id               = queue->sysjob;
7067
7068         r->printer_name         = lp_servicename(mem_ctx, snum);
7069         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7070         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7071         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7072         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7073         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7074         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7075         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7076         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7077         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7078         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7079         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7080         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7081         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7082         r->parameters           = talloc_strdup(mem_ctx, "");
7083         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7084         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7085         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7086
7087         r->devmode              = devmode;
7088
7089         r->text_status          = talloc_strdup(mem_ctx, "");
7090         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7091
7092         r->secdesc              = NULL;
7093
7094         r->status               = nt_printj_status(queue->status);
7095         r->priority             = queue->priority;
7096         r->position             = position;
7097         r->start_time           = 0;
7098         r->until_time           = 0;
7099         r->total_pages          = queue->page_count;
7100         r->size                 = queue->size;
7101         init_systemtime(&r->submitted, t);
7102         r->time                 = 0;
7103         r->pages_printed        = 0; /* ??? */
7104
7105         return WERR_OK;
7106 }
7107
7108 /****************************************************************************
7109 fill_job_info3
7110 ****************************************************************************/
7111
7112 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7113                              struct spoolss_JobInfo3 *r,
7114                              const print_queue_struct *queue,
7115                              const print_queue_struct *next_queue,
7116                              int position, int snum,
7117                              struct spoolss_PrinterInfo2 *pinfo2)
7118 {
7119         r->job_id               = queue->sysjob;
7120         r->next_job_id          = 0;
7121         if (next_queue) {
7122                 r->next_job_id  = next_queue->sysjob;
7123         }
7124         r->reserved             = 0;
7125
7126         return WERR_OK;
7127 }
7128
7129 /****************************************************************************
7130  Enumjobs at level 1.
7131 ****************************************************************************/
7132
7133 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7134                               const print_queue_struct *queue,
7135                               uint32_t num_queues, int snum,
7136                               struct spoolss_PrinterInfo2 *pinfo2,
7137                               union spoolss_JobInfo **info_p,
7138                               uint32_t *count)
7139 {
7140         union spoolss_JobInfo *info;
7141         int i;
7142         WERROR result = WERR_OK;
7143
7144         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7145         W_ERROR_HAVE_NO_MEMORY(info);
7146
7147         *count = num_queues;
7148
7149         for (i=0; i<*count; i++) {
7150                 result = fill_job_info1(info,
7151                                         &info[i].info1,
7152                                         &queue[i],
7153                                         i,
7154                                         snum,
7155                                         pinfo2);
7156                 if (!W_ERROR_IS_OK(result)) {
7157                         goto out;
7158                 }
7159         }
7160
7161  out:
7162         if (!W_ERROR_IS_OK(result)) {
7163                 TALLOC_FREE(info);
7164                 *count = 0;
7165                 return result;
7166         }
7167
7168         *info_p = info;
7169
7170         return WERR_OK;
7171 }
7172
7173 /****************************************************************************
7174  Enumjobs at level 2.
7175 ****************************************************************************/
7176
7177 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7178                               const print_queue_struct *queue,
7179                               uint32_t num_queues, int snum,
7180                               struct spoolss_PrinterInfo2 *pinfo2,
7181                               union spoolss_JobInfo **info_p,
7182                               uint32_t *count)
7183 {
7184         union spoolss_JobInfo *info;
7185         int i;
7186         WERROR result = WERR_OK;
7187
7188         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7189         W_ERROR_HAVE_NO_MEMORY(info);
7190
7191         *count = num_queues;
7192
7193         for (i=0; i<*count; i++) {
7194                 struct spoolss_DeviceMode *devmode;
7195
7196                 result = spoolss_create_default_devmode(info,
7197                                                         pinfo2->printername,
7198                                                         &devmode);
7199                 if (!W_ERROR_IS_OK(result)) {
7200                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7201                         goto out;
7202                 }
7203
7204                 result = fill_job_info2(info,
7205                                         &info[i].info2,
7206                                         &queue[i],
7207                                         i,
7208                                         snum,
7209                                         pinfo2,
7210                                         devmode);
7211                 if (!W_ERROR_IS_OK(result)) {
7212                         goto out;
7213                 }
7214         }
7215
7216  out:
7217         if (!W_ERROR_IS_OK(result)) {
7218                 TALLOC_FREE(info);
7219                 *count = 0;
7220                 return result;
7221         }
7222
7223         *info_p = info;
7224
7225         return WERR_OK;
7226 }
7227
7228 /****************************************************************************
7229  Enumjobs at level 3.
7230 ****************************************************************************/
7231
7232 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7233                               const print_queue_struct *queue,
7234                               uint32_t num_queues, int snum,
7235                               struct spoolss_PrinterInfo2 *pinfo2,
7236                               union spoolss_JobInfo **info_p,
7237                               uint32_t *count)
7238 {
7239         union spoolss_JobInfo *info;
7240         int i;
7241         WERROR result = WERR_OK;
7242
7243         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7244         W_ERROR_HAVE_NO_MEMORY(info);
7245
7246         *count = num_queues;
7247
7248         for (i=0; i<*count; i++) {
7249                 const print_queue_struct *next_queue = NULL;
7250
7251                 if (i+1 < *count) {
7252                         next_queue = &queue[i+1];
7253                 }
7254
7255                 result = fill_job_info3(info,
7256                                         &info[i].info3,
7257                                         &queue[i],
7258                                         next_queue,
7259                                         i,
7260                                         snum,
7261                                         pinfo2);
7262                 if (!W_ERROR_IS_OK(result)) {
7263                         goto out;
7264                 }
7265         }
7266
7267  out:
7268         if (!W_ERROR_IS_OK(result)) {
7269                 TALLOC_FREE(info);
7270                 *count = 0;
7271                 return result;
7272         }
7273
7274         *info_p = info;
7275
7276         return WERR_OK;
7277 }
7278
7279 /****************************************************************
7280  _spoolss_EnumJobs
7281 ****************************************************************/
7282
7283 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7284                          struct spoolss_EnumJobs *r)
7285 {
7286         WERROR result;
7287         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7288         int snum;
7289         print_status_struct prt_status;
7290         print_queue_struct *queue = NULL;
7291         uint32_t count;
7292
7293         /* that's an [in out] buffer */
7294
7295         if (!r->in.buffer && (r->in.offered != 0)) {
7296                 return WERR_INVALID_PARAM;
7297         }
7298
7299         DEBUG(4,("_spoolss_EnumJobs\n"));
7300
7301         *r->out.needed = 0;
7302         *r->out.count = 0;
7303         *r->out.info = NULL;
7304
7305         /* lookup the printer snum and tdb entry */
7306
7307         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7308                 return WERR_BADFID;
7309         }
7310
7311         result = winreg_get_printer_internal(p->mem_ctx,
7312                                     get_session_info_system(),
7313                                     p->msg_ctx,
7314                                     lp_const_servicename(snum),
7315                                     &pinfo2);
7316         if (!W_ERROR_IS_OK(result)) {
7317                 return result;
7318         }
7319
7320         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7321         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7322                 count, prt_status.status, prt_status.message));
7323
7324         if (count == 0) {
7325                 SAFE_FREE(queue);
7326                 TALLOC_FREE(pinfo2);
7327                 return WERR_OK;
7328         }
7329
7330         switch (r->in.level) {
7331         case 1:
7332                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7333                                          pinfo2, r->out.info, r->out.count);
7334                 break;
7335         case 2:
7336                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7337                                          pinfo2, r->out.info, r->out.count);
7338                 break;
7339         case 3:
7340                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7341                                          pinfo2, r->out.info, r->out.count);
7342                 break;
7343         default:
7344                 result = WERR_UNKNOWN_LEVEL;
7345                 break;
7346         }
7347
7348         SAFE_FREE(queue);
7349         TALLOC_FREE(pinfo2);
7350
7351         if (!W_ERROR_IS_OK(result)) {
7352                 return result;
7353         }
7354
7355         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7356                                                      spoolss_EnumJobs,
7357                                                      *r->out.info, r->in.level,
7358                                                      *r->out.count);
7359         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7360         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7361
7362         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7363 }
7364
7365 /****************************************************************
7366  _spoolss_ScheduleJob
7367 ****************************************************************/
7368
7369 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7370                             struct spoolss_ScheduleJob *r)
7371 {
7372         return WERR_OK;
7373 }
7374
7375 /****************************************************************
7376 ****************************************************************/
7377
7378 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7379                                struct messaging_context *msg_ctx,
7380                                const char *printer_name,
7381                                uint32_t job_id,
7382                                struct spoolss_SetJobInfo1 *r)
7383 {
7384         char *old_doc_name;
7385
7386         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7387                 return WERR_BADFID;
7388         }
7389
7390         if (strequal(old_doc_name, r->document_name)) {
7391                 return WERR_OK;
7392         }
7393
7394         if (!print_job_set_name(server_event_context(), msg_ctx,
7395                                 printer_name, job_id, r->document_name)) {
7396                 return WERR_BADFID;
7397         }
7398
7399         return WERR_OK;
7400 }
7401
7402 /****************************************************************
7403  _spoolss_SetJob
7404 ****************************************************************/
7405
7406 WERROR _spoolss_SetJob(struct pipes_struct *p,
7407                        struct spoolss_SetJob *r)
7408 {
7409         const struct auth_session_info *session_info = p->session_info;
7410         int snum;
7411         WERROR errcode = WERR_BADFUNC;
7412
7413         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7414                 return WERR_BADFID;
7415         }
7416
7417         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7418                 return WERR_INVALID_PRINTER_NAME;
7419         }
7420
7421         switch (r->in.command) {
7422         case SPOOLSS_JOB_CONTROL_CANCEL:
7423         case SPOOLSS_JOB_CONTROL_DELETE:
7424                 errcode = print_job_delete(session_info, p->msg_ctx,
7425                                            snum, r->in.job_id);
7426                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7427                         errcode = WERR_OK;
7428                 }
7429                 break;
7430         case SPOOLSS_JOB_CONTROL_PAUSE:
7431                 errcode = print_job_pause(session_info, p->msg_ctx,
7432                                           snum, r->in.job_id);
7433                 break;
7434         case SPOOLSS_JOB_CONTROL_RESTART:
7435         case SPOOLSS_JOB_CONTROL_RESUME:
7436                 errcode = print_job_resume(session_info, p->msg_ctx,
7437                                            snum, r->in.job_id);
7438                 break;
7439         case 0:
7440                 errcode = WERR_OK;
7441                 break;
7442         default:
7443                 return WERR_UNKNOWN_LEVEL;
7444         }
7445
7446         if (!W_ERROR_IS_OK(errcode)) {
7447                 return errcode;
7448         }
7449
7450         if (r->in.ctr == NULL) {
7451                 return errcode;
7452         }
7453
7454         switch (r->in.ctr->level) {
7455         case 1:
7456                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7457                                            lp_const_servicename(snum),
7458                                            r->in.job_id,
7459                                            r->in.ctr->info.info1);
7460                 break;
7461         case 2:
7462         case 3:
7463         case 4:
7464         default:
7465                 return WERR_UNKNOWN_LEVEL;
7466         }
7467
7468         return errcode;
7469 }
7470
7471 /****************************************************************************
7472  Enumerates all printer drivers by level and architecture.
7473 ****************************************************************************/
7474
7475 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7476                                                        const struct auth_session_info *session_info,
7477                                                        struct messaging_context *msg_ctx,
7478                                                        const char *servername,
7479                                                        const char *architecture,
7480                                                        uint32_t level,
7481                                                        union spoolss_DriverInfo **info_p,
7482                                                        uint32_t *count_p)
7483 {
7484         int i;
7485         uint32_t version;
7486         struct spoolss_DriverInfo8 *driver;
7487         union spoolss_DriverInfo *info = NULL;
7488         uint32_t count = 0;
7489         WERROR result = WERR_OK;
7490         uint32_t num_drivers;
7491         const char **drivers;
7492         struct dcerpc_binding_handle *b;
7493         TALLOC_CTX *tmp_ctx = NULL;
7494
7495         *count_p = 0;
7496         *info_p = NULL;
7497
7498         tmp_ctx = talloc_new(mem_ctx);
7499         if (!tmp_ctx) {
7500                 return WERR_NOMEM;
7501         }
7502
7503         result = winreg_printer_binding_handle(tmp_ctx,
7504                                                session_info,
7505                                                msg_ctx,
7506                                                &b);
7507         if (!W_ERROR_IS_OK(result)) {
7508                 goto out;
7509         }
7510
7511         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7512                 result = winreg_get_driver_list(tmp_ctx, b,
7513                                                 architecture, version,
7514                                                 &num_drivers, &drivers);
7515                 if (!W_ERROR_IS_OK(result)) {
7516                         goto out;
7517                 }
7518                 DEBUG(4, ("we have:[%d] drivers in environment"
7519                           " [%s] and version [%d]\n",
7520                           num_drivers, architecture, version));
7521
7522                 if (num_drivers != 0) {
7523                         info = talloc_realloc(tmp_ctx, info,
7524                                                     union spoolss_DriverInfo,
7525                                                     count + num_drivers);
7526                         if (!info) {
7527                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7528                                         "failed to enlarge driver info buffer!\n"));
7529                                 result = WERR_NOMEM;
7530                                 goto out;
7531                         }
7532                 }
7533
7534                 for (i = 0; i < num_drivers; i++) {
7535                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7536
7537                         result = winreg_get_driver(tmp_ctx, b,
7538                                                    architecture, drivers[i],
7539                                                    version, &driver);
7540                         if (!W_ERROR_IS_OK(result)) {
7541                                 goto out;
7542                         }
7543
7544                         switch (level) {
7545                         case 1:
7546                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7547                                                                    driver, servername);
7548                                 break;
7549                         case 2:
7550                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7551                                                                    driver, servername);
7552                                 break;
7553                         case 3:
7554                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7555                                                                    driver, servername);
7556                                 break;
7557                         case 4:
7558                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7559                                                                    driver, servername);
7560                                 break;
7561                         case 5:
7562                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7563                                                                    driver, servername);
7564                                 break;
7565                         case 6:
7566                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7567                                                                    driver, servername);
7568                                 break;
7569                         case 8:
7570                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7571                                                                    driver, servername);
7572                                 break;
7573                         default:
7574                                 result = WERR_UNKNOWN_LEVEL;
7575                                 break;
7576                         }
7577
7578                         TALLOC_FREE(driver);
7579
7580                         if (!W_ERROR_IS_OK(result)) {
7581                                 goto out;
7582                         }
7583                 }
7584
7585                 count += num_drivers;
7586                 TALLOC_FREE(drivers);
7587         }
7588
7589 out:
7590         if (W_ERROR_IS_OK(result)) {
7591                 *info_p = talloc_move(mem_ctx, &info);
7592                 *count_p = count;
7593         }
7594
7595         talloc_free(tmp_ctx);
7596         return result;
7597 }
7598
7599 /****************************************************************************
7600  Enumerates all printer drivers by level.
7601 ****************************************************************************/
7602
7603 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7604                                        const struct auth_session_info *session_info,
7605                                        struct messaging_context *msg_ctx,
7606                                        const char *servername,
7607                                        const char *architecture,
7608                                        uint32_t level,
7609                                        union spoolss_DriverInfo **info_p,
7610                                        uint32_t *count_p)
7611 {
7612         uint32_t a,i;
7613         WERROR result = WERR_OK;
7614
7615         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7616
7617                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7618
7619                         union spoolss_DriverInfo *info = NULL;
7620                         uint32_t count = 0;
7621
7622                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7623                                                                           session_info,
7624                                                                           msg_ctx,
7625                                                                           servername,
7626                                                                           archi_table[a].long_archi,
7627                                                                           level,
7628                                                                           &info,
7629                                                                           &count);
7630                         if (!W_ERROR_IS_OK(result)) {
7631                                 continue;
7632                         }
7633
7634                         for (i=0; i < count; i++) {
7635                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7636                                              info[i], info_p, count_p);
7637                         }
7638                 }
7639
7640                 return result;
7641         }
7642
7643         return enumprinterdrivers_level_by_architecture(mem_ctx,
7644                                                         session_info,
7645                                                         msg_ctx,
7646                                                         servername,
7647                                                         architecture,
7648                                                         level,
7649                                                         info_p,
7650                                                         count_p);
7651 }
7652
7653 /****************************************************************
7654  _spoolss_EnumPrinterDrivers
7655 ****************************************************************/
7656
7657 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7658                                    struct spoolss_EnumPrinterDrivers *r)
7659 {
7660         const char *cservername;
7661         WERROR result;
7662
7663         /* that's an [in out] buffer */
7664
7665         if (!r->in.buffer && (r->in.offered != 0)) {
7666                 return WERR_INVALID_PARAM;
7667         }
7668
7669         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7670
7671         *r->out.needed = 0;
7672         *r->out.count = 0;
7673         *r->out.info = NULL;
7674
7675         cservername = canon_servername(r->in.server);
7676
7677         if (!is_myname_or_ipaddr(cservername)) {
7678                 return WERR_UNKNOWN_PRINTER_DRIVER;
7679         }
7680
7681         result = enumprinterdrivers_level(p->mem_ctx,
7682                                           get_session_info_system(),
7683                                           p->msg_ctx,
7684                                           cservername,
7685                                           r->in.environment,
7686                                           r->in.level,
7687                                           r->out.info,
7688                                           r->out.count);
7689         if (!W_ERROR_IS_OK(result)) {
7690                 return result;
7691         }
7692
7693         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7694                                                      spoolss_EnumPrinterDrivers,
7695                                                      *r->out.info, r->in.level,
7696                                                      *r->out.count);
7697         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7698         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7699
7700         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7701 }
7702
7703 /****************************************************************
7704  _spoolss_EnumForms
7705 ****************************************************************/
7706
7707 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7708                           struct spoolss_EnumForms *r)
7709 {
7710         WERROR result;
7711
7712         *r->out.count = 0;
7713         *r->out.needed = 0;
7714         *r->out.info = NULL;
7715
7716         /* that's an [in out] buffer */
7717
7718         if (!r->in.buffer && (r->in.offered != 0) ) {
7719                 return WERR_INVALID_PARAM;
7720         }
7721
7722         DEBUG(4,("_spoolss_EnumForms\n"));
7723         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7724         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7725
7726         switch (r->in.level) {
7727         case 1:
7728                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7729                                                    get_session_info_system(),
7730                                                    p->msg_ctx,
7731                                                    r->out.count,
7732                                                    r->out.info);
7733                 break;
7734         default:
7735                 result = WERR_UNKNOWN_LEVEL;
7736                 break;
7737         }
7738
7739         if (!W_ERROR_IS_OK(result)) {
7740                 return result;
7741         }
7742
7743         if (*r->out.count == 0) {
7744                 return WERR_NO_MORE_ITEMS;
7745         }
7746
7747         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7748                                                      spoolss_EnumForms,
7749                                                      *r->out.info, r->in.level,
7750                                                      *r->out.count);
7751         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7752         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7753
7754         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7755 }
7756
7757 /****************************************************************
7758  _spoolss_GetForm
7759 ****************************************************************/
7760
7761 WERROR _spoolss_GetForm(struct pipes_struct *p,
7762                         struct spoolss_GetForm *r)
7763 {
7764         WERROR result;
7765
7766         /* that's an [in out] buffer */
7767
7768         if (!r->in.buffer && (r->in.offered != 0)) {
7769                 return WERR_INVALID_PARAM;
7770         }
7771
7772         DEBUG(4,("_spoolss_GetForm\n"));
7773         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7774         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7775
7776         switch (r->in.level) {
7777         case 1:
7778                 result = winreg_printer_getform1_internal(p->mem_ctx,
7779                                                  get_session_info_system(),
7780                                                  p->msg_ctx,
7781                                                  r->in.form_name,
7782                                                  &r->out.info->info1);
7783                 break;
7784         default:
7785                 result = WERR_UNKNOWN_LEVEL;
7786                 break;
7787         }
7788
7789         if (!W_ERROR_IS_OK(result)) {
7790                 TALLOC_FREE(r->out.info);
7791                 return result;
7792         }
7793
7794         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7795                                                r->out.info, r->in.level);
7796         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7797
7798         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7799 }
7800
7801 /****************************************************************************
7802 ****************************************************************************/
7803
7804 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7805                           struct spoolss_PortInfo1 *r,
7806                           const char *name)
7807 {
7808         r->port_name = talloc_strdup(mem_ctx, name);
7809         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7810
7811         return WERR_OK;
7812 }
7813
7814 /****************************************************************************
7815  TODO: This probably needs distinguish between TCP/IP and Local ports
7816  somehow.
7817 ****************************************************************************/
7818
7819 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7820                           struct spoolss_PortInfo2 *r,
7821                           const char *name)
7822 {
7823         r->port_name = talloc_strdup(mem_ctx, name);
7824         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7825
7826         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7827         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7828
7829         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7830         W_ERROR_HAVE_NO_MEMORY(r->description);
7831
7832         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7833         r->reserved = 0;
7834
7835         return WERR_OK;
7836 }
7837
7838
7839 /****************************************************************************
7840  wrapper around the enumer ports command
7841 ****************************************************************************/
7842
7843 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7844 {
7845         char *cmd = lp_enumports_cmd(talloc_tos());
7846         char **qlines = NULL;
7847         char *command = NULL;
7848         int numlines;
7849         int ret;
7850         int fd;
7851
7852         *count = 0;
7853         *lines = NULL;
7854
7855         /* if no hook then just fill in the default port */
7856
7857         if ( !*cmd ) {
7858                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7859                         return WERR_NOMEM;
7860                 }
7861                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7862                         TALLOC_FREE(qlines);
7863                         return WERR_NOMEM;
7864                 }
7865                 qlines[1] = NULL;
7866                 numlines = 1;
7867         }
7868         else {
7869                 /* we have a valid enumport command */
7870
7871                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7872                 if (!command) {
7873                         return WERR_NOMEM;
7874                 }
7875
7876                 DEBUG(10,("Running [%s]\n", command));
7877                 ret = smbrun(command, &fd);
7878                 DEBUG(10,("Returned [%d]\n", ret));
7879                 TALLOC_FREE(command);
7880                 if (ret != 0) {
7881                         if (fd != -1) {
7882                                 close(fd);
7883                         }
7884                         return WERR_ACCESS_DENIED;
7885                 }
7886
7887                 numlines = 0;
7888                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7889                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7890                 close(fd);
7891         }
7892
7893         *count = numlines;
7894         *lines = qlines;
7895
7896         return WERR_OK;
7897 }
7898
7899 /****************************************************************************
7900  enumports level 1.
7901 ****************************************************************************/
7902
7903 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7904                                 union spoolss_PortInfo **info_p,
7905                                 uint32_t *count)
7906 {
7907         union spoolss_PortInfo *info = NULL;
7908         int i=0;
7909         WERROR result = WERR_OK;
7910         char **qlines = NULL;
7911         int numlines = 0;
7912
7913         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7914         if (!W_ERROR_IS_OK(result)) {
7915                 goto out;
7916         }
7917
7918         if (numlines) {
7919                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7920                 if (!info) {
7921                         DEBUG(10,("Returning WERR_NOMEM\n"));
7922                         result = WERR_NOMEM;
7923                         goto out;
7924                 }
7925
7926                 for (i=0; i<numlines; i++) {
7927                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7928                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7929                         if (!W_ERROR_IS_OK(result)) {
7930                                 goto out;
7931                         }
7932                 }
7933         }
7934         TALLOC_FREE(qlines);
7935
7936 out:
7937         if (!W_ERROR_IS_OK(result)) {
7938                 TALLOC_FREE(info);
7939                 TALLOC_FREE(qlines);
7940                 *count = 0;
7941                 *info_p = NULL;
7942                 return result;
7943         }
7944
7945         *info_p = info;
7946         *count = numlines;
7947
7948         return WERR_OK;
7949 }
7950
7951 /****************************************************************************
7952  enumports level 2.
7953 ****************************************************************************/
7954
7955 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7956                                 union spoolss_PortInfo **info_p,
7957                                 uint32_t *count)
7958 {
7959         union spoolss_PortInfo *info = NULL;
7960         int i=0;
7961         WERROR result = WERR_OK;
7962         char **qlines = NULL;
7963         int numlines = 0;
7964
7965         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7966         if (!W_ERROR_IS_OK(result)) {
7967                 goto out;
7968         }
7969
7970         if (numlines) {
7971                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7972                 if (!info) {
7973                         DEBUG(10,("Returning WERR_NOMEM\n"));
7974                         result = WERR_NOMEM;
7975                         goto out;
7976                 }
7977
7978                 for (i=0; i<numlines; i++) {
7979                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7980                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7981                         if (!W_ERROR_IS_OK(result)) {
7982                                 goto out;
7983                         }
7984                 }
7985         }
7986         TALLOC_FREE(qlines);
7987
7988 out:
7989         if (!W_ERROR_IS_OK(result)) {
7990                 TALLOC_FREE(info);
7991                 TALLOC_FREE(qlines);
7992                 *count = 0;
7993                 *info_p = NULL;
7994                 return result;
7995         }
7996
7997         *info_p = info;
7998         *count = numlines;
7999
8000         return WERR_OK;
8001 }
8002
8003 /****************************************************************
8004  _spoolss_EnumPorts
8005 ****************************************************************/
8006
8007 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8008                           struct spoolss_EnumPorts *r)
8009 {
8010         WERROR result;
8011
8012         /* that's an [in out] buffer */
8013
8014         if (!r->in.buffer && (r->in.offered != 0)) {
8015                 return WERR_INVALID_PARAM;
8016         }
8017
8018         DEBUG(4,("_spoolss_EnumPorts\n"));
8019
8020         *r->out.count = 0;
8021         *r->out.needed = 0;
8022         *r->out.info = NULL;
8023
8024         switch (r->in.level) {
8025         case 1:
8026                 result = enumports_level_1(p->mem_ctx, r->out.info,
8027                                            r->out.count);
8028                 break;
8029         case 2:
8030                 result = enumports_level_2(p->mem_ctx, r->out.info,
8031                                            r->out.count);
8032                 break;
8033         default:
8034                 return WERR_UNKNOWN_LEVEL;
8035         }
8036
8037         if (!W_ERROR_IS_OK(result)) {
8038                 return result;
8039         }
8040
8041         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8042                                                      spoolss_EnumPorts,
8043                                                      *r->out.info, r->in.level,
8044                                                      *r->out.count);
8045         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8046         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8047
8048         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8049 }
8050
8051 /****************************************************************************
8052 ****************************************************************************/
8053
8054 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8055                                            const char *server,
8056                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8057                                            struct spoolss_DeviceMode *devmode,
8058                                            struct security_descriptor *secdesc,
8059                                            struct spoolss_UserLevelCtr *user_ctr,
8060                                            struct policy_handle *handle)
8061 {
8062         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8063         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8064         int     snum;
8065         WERROR err = WERR_OK;
8066
8067         /* samba does not have a concept of local, non-shared printers yet, so
8068          * make sure we always setup sharename - gd */
8069         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8070             (info2->printername != NULL && info2->printername[0] != '\0')) {
8071                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8072                         "no sharename has been set, setting printername %s as sharename\n",
8073                         info2->printername));
8074                 info2->sharename = info2->printername;
8075         }
8076
8077         /* check to see if the printer already exists */
8078         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8079                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8080                         info2->sharename));
8081                 return WERR_PRINTER_ALREADY_EXISTS;
8082         }
8083
8084         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8085                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8086                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8087                                 info2->printername));
8088                         return WERR_PRINTER_ALREADY_EXISTS;
8089                 }
8090         }
8091
8092         /* validate printer info struct */
8093         if (!info2->printername || strlen(info2->printername) == 0) {
8094                 return WERR_INVALID_PRINTER_NAME;
8095         }
8096         if (!info2->portname || strlen(info2->portname) == 0) {
8097                 return WERR_UNKNOWN_PORT;
8098         }
8099         if (!info2->drivername || strlen(info2->drivername) == 0) {
8100                 return WERR_UNKNOWN_PRINTER_DRIVER;
8101         }
8102         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8103                 return WERR_UNKNOWN_PRINTPROCESSOR;
8104         }
8105
8106         /* FIXME!!!  smbd should check to see if the driver is installed before
8107            trying to add a printer like this  --jerry */
8108
8109         if (*lp_addprinter_cmd(talloc_tos()) ) {
8110                 char *raddr;
8111
8112                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8113                                                          p->mem_ctx);
8114                 if (raddr == NULL) {
8115                         return WERR_NOMEM;
8116                 }
8117
8118                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8119                                        info2, raddr,
8120                                        p->msg_ctx) ) {
8121                         return WERR_ACCESS_DENIED;
8122                 }
8123         } else {
8124                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8125                         "smb.conf parameter \"addprinter command\" is defined. This "
8126                         "parameter must exist for this call to succeed\n",
8127                         info2->sharename ));
8128         }
8129
8130         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8131                 return WERR_ACCESS_DENIED;
8132         }
8133
8134         /* you must be a printer admin to add a new printer */
8135         if (!print_access_check(p->session_info,
8136                                 p->msg_ctx,
8137                                 snum,
8138                                 PRINTER_ACCESS_ADMINISTER)) {
8139                 return WERR_ACCESS_DENIED;
8140         }
8141
8142         /*
8143          * Do sanity check on the requested changes for Samba.
8144          */
8145
8146         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8147                 return WERR_INVALID_PARAM;
8148         }
8149
8150         if (devmode == NULL) {
8151                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8152         }
8153
8154         err = update_dsspooler(p->mem_ctx,
8155                                get_session_info_system(),
8156                                p->msg_ctx,
8157                                0,
8158                                info2,
8159                                NULL);
8160         if (!W_ERROR_IS_OK(err)) {
8161                 return err;
8162         }
8163
8164         err = winreg_update_printer_internal(p->mem_ctx,
8165                                     get_session_info_system(),
8166                                     p->msg_ctx,
8167                                     info2->sharename,
8168                                     info2_mask,
8169                                     info2,
8170                                     devmode,
8171                                     secdesc);
8172         if (!W_ERROR_IS_OK(err)) {
8173                 return err;
8174         }
8175
8176         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8177         if (!W_ERROR_IS_OK(err)) {
8178                 /* Handle open failed - remove addition. */
8179                 ZERO_STRUCTP(handle);
8180                 return err;
8181         }
8182
8183         return WERR_OK;
8184 }
8185
8186 /****************************************************************
8187  _spoolss_AddPrinterEx
8188 ****************************************************************/
8189
8190 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8191                              struct spoolss_AddPrinterEx *r)
8192 {
8193         switch (r->in.info_ctr->level) {
8194         case 1:
8195                 /* we don't handle yet */
8196                 /* but I know what to do ... */
8197                 return WERR_UNKNOWN_LEVEL;
8198         case 2:
8199                 return spoolss_addprinterex_level_2(p, r->in.server,
8200                                                     r->in.info_ctr,
8201                                                     r->in.devmode_ctr->devmode,
8202                                                     r->in.secdesc_ctr->sd,
8203                                                     r->in.userlevel_ctr,
8204                                                     r->out.handle);
8205         default:
8206                 return WERR_UNKNOWN_LEVEL;
8207         }
8208 }
8209
8210 /****************************************************************
8211  _spoolss_AddPrinter
8212 ****************************************************************/
8213
8214 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8215                            struct spoolss_AddPrinter *r)
8216 {
8217         struct spoolss_AddPrinterEx a;
8218         struct spoolss_UserLevelCtr userlevel_ctr;
8219
8220         ZERO_STRUCT(userlevel_ctr);
8221
8222         userlevel_ctr.level = 1;
8223
8224         a.in.server             = r->in.server;
8225         a.in.info_ctr           = r->in.info_ctr;
8226         a.in.devmode_ctr        = r->in.devmode_ctr;
8227         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8228         a.in.userlevel_ctr      = &userlevel_ctr;
8229         a.out.handle            = r->out.handle;
8230
8231         return _spoolss_AddPrinterEx(p, &a);
8232 }
8233
8234 /****************************************************************
8235  _spoolss_AddPrinterDriverEx
8236 ****************************************************************/
8237
8238 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8239                                    struct spoolss_AddPrinterDriverEx *r)
8240 {
8241         WERROR err = WERR_OK;
8242         const char *driver_name = NULL;
8243         uint32_t version;
8244         const char *fn;
8245
8246         switch (p->opnum) {
8247                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8248                         fn = "_spoolss_AddPrinterDriver";
8249                         break;
8250                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8251                         fn = "_spoolss_AddPrinterDriverEx";
8252                         break;
8253                 default:
8254                         return WERR_INVALID_PARAM;
8255         }
8256
8257         /*
8258          * we only support the semantics of AddPrinterDriver()
8259          * i.e. only copy files that are newer than existing ones
8260          */
8261
8262         if (r->in.flags == 0) {
8263                 return WERR_INVALID_PARAM;
8264         }
8265
8266         if (r->in.flags != APD_COPY_NEW_FILES) {
8267                 return WERR_ACCESS_DENIED;
8268         }
8269
8270         /* FIXME */
8271         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8272                 /* Clever hack from Martin Zielinski <mz@seh.de>
8273                  * to allow downgrade from level 8 (Vista).
8274                  */
8275                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8276                         r->in.info_ctr->level));
8277                 return WERR_UNKNOWN_LEVEL;
8278         }
8279
8280         DEBUG(5,("Cleaning driver's information\n"));
8281         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8282         if (!W_ERROR_IS_OK(err))
8283                 goto done;
8284
8285         DEBUG(5,("Moving driver to final destination\n"));
8286         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8287         if (!W_ERROR_IS_OK(err)) {
8288                 goto done;
8289         }
8290
8291         err = winreg_add_driver_internal(p->mem_ctx,
8292                                 get_session_info_system(),
8293                                 p->msg_ctx,
8294                                 r->in.info_ctr,
8295                                 &driver_name,
8296                                 &version);
8297         if (!W_ERROR_IS_OK(err)) {
8298                 goto done;
8299         }
8300
8301         /*
8302          * I think this is where he DrvUpgradePrinter() hook would be
8303          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8304          * server.  Right now, we just need to send ourselves a message
8305          * to update each printer bound to this driver.   --jerry
8306          */
8307
8308         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8309                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8310                         fn, driver_name));
8311         }
8312
8313 done:
8314         return err;
8315 }
8316
8317 /****************************************************************
8318  _spoolss_AddPrinterDriver
8319 ****************************************************************/
8320
8321 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8322                                  struct spoolss_AddPrinterDriver *r)
8323 {
8324         struct spoolss_AddPrinterDriverEx a;
8325
8326         switch (r->in.info_ctr->level) {
8327         case 2:
8328         case 3:
8329         case 4:
8330         case 5:
8331                 break;
8332         default:
8333                 return WERR_UNKNOWN_LEVEL;
8334         }
8335
8336         a.in.servername         = r->in.servername;
8337         a.in.info_ctr           = r->in.info_ctr;
8338         a.in.flags              = APD_COPY_NEW_FILES;
8339
8340         return _spoolss_AddPrinterDriverEx(p, &a);
8341 }
8342
8343 /****************************************************************************
8344 ****************************************************************************/
8345
8346 struct _spoolss_paths {
8347         int type;
8348         const char *share;
8349         const char *dir;
8350 };
8351
8352 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8353
8354 static const struct _spoolss_paths spoolss_paths[]= {
8355         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8356         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8357 };
8358
8359 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8360                                           const char *servername,
8361                                           const char *environment,
8362                                           int component,
8363                                           char **path)
8364 {
8365         const char *pservername = NULL;
8366         const char *long_archi;
8367         const char *short_archi;
8368
8369         *path = NULL;
8370
8371         /* environment may be empty */
8372         if (environment && strlen(environment)) {
8373                 long_archi = environment;
8374         } else {
8375                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8376                                                   "spoolss", "architecture",
8377                                                   SPOOLSS_ARCHITECTURE_NT_X86);
8378         }
8379
8380         /* servername may be empty */
8381         if (servername && strlen(servername)) {
8382                 pservername = canon_servername(servername);
8383
8384                 if (!is_myname_or_ipaddr(pservername)) {
8385                         return WERR_INVALID_PARAM;
8386                 }
8387         }
8388
8389         if (!(short_archi = get_short_archi(long_archi))) {
8390                 return WERR_INVALID_ENVIRONMENT;
8391         }
8392
8393         switch (component) {
8394         case SPOOLSS_PRTPROCS_PATH:
8395         case SPOOLSS_DRIVER_PATH:
8396                 if (pservername) {
8397                         *path = talloc_asprintf(mem_ctx,
8398                                         "\\\\%s\\%s\\%s",
8399                                         pservername,
8400                                         spoolss_paths[component].share,
8401                                         short_archi);
8402                 } else {
8403                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8404                                         SPOOLSS_DEFAULT_SERVER_PATH,
8405                                         spoolss_paths[component].dir,
8406                                         short_archi);
8407                 }
8408                 break;
8409         default:
8410                 return WERR_INVALID_PARAM;
8411         }
8412
8413         if (!*path) {
8414                 return WERR_NOMEM;
8415         }
8416
8417         return WERR_OK;
8418 }
8419
8420 /****************************************************************************
8421 ****************************************************************************/
8422
8423 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8424                                           const char *servername,
8425                                           const char *environment,
8426                                           struct spoolss_DriverDirectoryInfo1 *r)
8427 {
8428         WERROR werr;
8429         char *path = NULL;
8430
8431         werr = compose_spoolss_server_path(mem_ctx,
8432                                            servername,
8433                                            environment,
8434                                            SPOOLSS_DRIVER_PATH,
8435                                            &path);
8436         if (!W_ERROR_IS_OK(werr)) {
8437                 return werr;
8438         }
8439
8440         DEBUG(4,("printer driver directory: [%s]\n", path));
8441
8442         r->directory_name = path;
8443
8444         return WERR_OK;
8445 }
8446
8447 /****************************************************************
8448  _spoolss_GetPrinterDriverDirectory
8449 ****************************************************************/
8450
8451 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8452                                           struct spoolss_GetPrinterDriverDirectory *r)
8453 {
8454         WERROR werror;
8455
8456         /* that's an [in out] buffer */
8457
8458         if (!r->in.buffer && (r->in.offered != 0)) {
8459                 return WERR_INVALID_PARAM;
8460         }
8461
8462         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8463                 r->in.level));
8464
8465         *r->out.needed = 0;
8466
8467         /* r->in.level is ignored */
8468
8469         werror = getprinterdriverdir_level_1(p->mem_ctx,
8470                                              r->in.server,
8471                                              r->in.environment,
8472                                              &r->out.info->info1);
8473         if (!W_ERROR_IS_OK(werror)) {
8474                 TALLOC_FREE(r->out.info);
8475                 return werror;
8476         }
8477
8478         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8479                                                r->out.info, r->in.level);
8480         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8481
8482         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8483 }
8484
8485 /****************************************************************
8486  _spoolss_EnumPrinterData
8487 ****************************************************************/
8488
8489 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8490                                 struct spoolss_EnumPrinterData *r)
8491 {
8492         WERROR result;
8493         struct spoolss_EnumPrinterDataEx r2;
8494         uint32_t count;
8495         struct spoolss_PrinterEnumValues *info, *val = NULL;
8496         uint32_t needed;
8497
8498         r2.in.handle    = r->in.handle;
8499         r2.in.key_name  = "PrinterDriverData";
8500         r2.in.offered   = 0;
8501         r2.out.count    = &count;
8502         r2.out.info     = &info;
8503         r2.out.needed   = &needed;
8504
8505         result = _spoolss_EnumPrinterDataEx(p, &r2);
8506         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8507                 r2.in.offered = needed;
8508                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8509         }
8510         if (!W_ERROR_IS_OK(result)) {
8511                 return result;
8512         }
8513
8514         /*
8515          * The NT machine wants to know the biggest size of value and data
8516          *
8517          * cf: MSDN EnumPrinterData remark section
8518          */
8519
8520         if (!r->in.value_offered && !r->in.data_offered) {
8521                 uint32_t biggest_valuesize = 0;
8522                 uint32_t biggest_datasize = 0;
8523                 int i, name_length;
8524
8525                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8526
8527                 for (i=0; i<count; i++) {
8528
8529                         name_length = strlen(info[i].value_name);
8530                         if (strlen(info[i].value_name) > biggest_valuesize) {
8531                                 biggest_valuesize = name_length;
8532                         }
8533
8534                         if (info[i].data_length > biggest_datasize) {
8535                                 biggest_datasize = info[i].data_length;
8536                         }
8537
8538                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8539                                 biggest_datasize));
8540                 }
8541
8542                 /* the value is an UNICODE string but real_value_size is the length
8543                    in bytes including the trailing 0 */
8544
8545                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8546                 *r->out.data_needed  = biggest_datasize;
8547
8548                 DEBUG(6,("final values: [%d], [%d]\n",
8549                         *r->out.value_needed, *r->out.data_needed));
8550
8551                 return WERR_OK;
8552         }
8553
8554         if (r->in.enum_index < count) {
8555                 val = &info[r->in.enum_index];
8556         }
8557
8558         if (val == NULL) {
8559                 /* out_value should default to "" or else NT4 has
8560                    problems unmarshalling the response */
8561
8562                 if (r->in.value_offered) {
8563                         *r->out.value_needed = 1;
8564                         r->out.value_name = talloc_strdup(r, "");
8565                         if (!r->out.value_name) {
8566                                 return WERR_NOMEM;
8567                         }
8568                 } else {
8569                         r->out.value_name = NULL;
8570                         *r->out.value_needed = 0;
8571                 }
8572
8573                 /* the data is counted in bytes */
8574
8575                 *r->out.data_needed = r->in.data_offered;
8576
8577                 result = WERR_NO_MORE_ITEMS;
8578         } else {
8579                 /*
8580                  * the value is:
8581                  * - counted in bytes in the request
8582                  * - counted in UNICODE chars in the max reply
8583                  * - counted in bytes in the real size
8584                  *
8585                  * take a pause *before* coding not *during* coding
8586                  */
8587
8588                 /* name */
8589                 if (r->in.value_offered) {
8590                         r->out.value_name = talloc_strdup(r, val->value_name);
8591                         if (!r->out.value_name) {
8592                                 return WERR_NOMEM;
8593                         }
8594                         *r->out.value_needed = val->value_name_len;
8595                 } else {
8596                         r->out.value_name = NULL;
8597                         *r->out.value_needed = 0;
8598                 }
8599
8600                 /* type */
8601
8602                 *r->out.type = val->type;
8603
8604                 /* data - counted in bytes */
8605
8606                 /*
8607                  * See the section "Dynamically Typed Query Parameters"
8608                  * in MS-RPRN.
8609                  */
8610
8611                 if (r->out.data && val->data && val->data->data &&
8612                                 val->data_length && r->in.data_offered) {
8613                         memcpy(r->out.data, val->data->data,
8614                                 MIN(val->data_length,r->in.data_offered));
8615                 }
8616
8617                 *r->out.data_needed = val->data_length;
8618
8619                 result = WERR_OK;
8620         }
8621
8622         return result;
8623 }
8624
8625 /****************************************************************
8626  _spoolss_SetPrinterData
8627 ****************************************************************/
8628
8629 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8630                                struct spoolss_SetPrinterData *r)
8631 {
8632         struct spoolss_SetPrinterDataEx r2;
8633
8634         r2.in.handle            = r->in.handle;
8635         r2.in.key_name          = "PrinterDriverData";
8636         r2.in.value_name        = r->in.value_name;
8637         r2.in.type              = r->in.type;
8638         r2.in.data              = r->in.data;
8639         r2.in.offered           = r->in.offered;
8640
8641         return _spoolss_SetPrinterDataEx(p, &r2);
8642 }
8643
8644 /****************************************************************
8645  _spoolss_ResetPrinter
8646 ****************************************************************/
8647
8648 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8649                              struct spoolss_ResetPrinter *r)
8650 {
8651         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8652         int             snum;
8653
8654         DEBUG(5,("_spoolss_ResetPrinter\n"));
8655
8656         /*
8657          * All we do is to check to see if the handle and queue is valid.
8658          * This call really doesn't mean anything to us because we only
8659          * support RAW printing.   --jerry
8660          */
8661
8662         if (!Printer) {
8663                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8664                         OUR_HANDLE(r->in.handle)));
8665                 return WERR_BADFID;
8666         }
8667
8668         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8669                 return WERR_BADFID;
8670
8671
8672         /* blindly return success */
8673         return WERR_OK;
8674 }
8675
8676 /****************************************************************
8677  _spoolss_DeletePrinterData
8678 ****************************************************************/
8679
8680 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8681                                   struct spoolss_DeletePrinterData *r)
8682 {
8683         struct spoolss_DeletePrinterDataEx r2;
8684
8685         r2.in.handle            = r->in.handle;
8686         r2.in.key_name          = "PrinterDriverData";
8687         r2.in.value_name        = r->in.value_name;
8688
8689         return _spoolss_DeletePrinterDataEx(p, &r2);
8690 }
8691
8692 /****************************************************************
8693  _spoolss_AddForm
8694 ****************************************************************/
8695
8696 WERROR _spoolss_AddForm(struct pipes_struct *p,
8697                         struct spoolss_AddForm *r)
8698 {
8699         struct spoolss_AddFormInfo1 *form;
8700         int snum = -1;
8701         WERROR status = WERR_OK;
8702         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8703         struct dcerpc_binding_handle *b;
8704         TALLOC_CTX *tmp_ctx = NULL;
8705
8706         DEBUG(5,("_spoolss_AddForm\n"));
8707
8708         if (!Printer) {
8709                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8710                         OUR_HANDLE(r->in.handle)));
8711                 return WERR_BADFID;
8712         }
8713
8714         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8715            and not a printer admin, then fail */
8716
8717         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8718             !security_token_has_privilege(p->session_info->security_token,
8719                                           SEC_PRIV_PRINT_OPERATOR)) {
8720                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8721                 return WERR_ACCESS_DENIED;
8722         }
8723
8724         if (r->in.info_ctr->level != 1) {
8725                 return WERR_INVALID_LEVEL;
8726         }
8727
8728         form = r->in.info_ctr->info.info1;
8729         if (!form) {
8730                 return WERR_INVALID_PARAM;
8731         }
8732
8733         switch (form->flags) {
8734         case SPOOLSS_FORM_USER:
8735         case SPOOLSS_FORM_BUILTIN:
8736         case SPOOLSS_FORM_PRINTER:
8737                 break;
8738         default:
8739                 return WERR_INVALID_PARAM;
8740         }
8741
8742         tmp_ctx = talloc_new(p->mem_ctx);
8743         if (!tmp_ctx) {
8744                 return WERR_NOMEM;
8745         }
8746
8747         status = winreg_printer_binding_handle(tmp_ctx,
8748                                                get_session_info_system(),
8749                                                p->msg_ctx,
8750                                                &b);
8751         if (!W_ERROR_IS_OK(status)) {
8752                 goto done;
8753         }
8754
8755         status = winreg_printer_addform1(tmp_ctx, b, form);
8756         if (!W_ERROR_IS_OK(status)) {
8757                 goto done;
8758         }
8759
8760         /*
8761          * ChangeID must always be set if this is a printer
8762          */
8763         if (Printer->printer_type == SPLHND_PRINTER) {
8764                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8765                         status = WERR_BADFID;
8766                         goto done;
8767                 }
8768
8769                 status = winreg_printer_update_changeid(tmp_ctx, b,
8770                                                         lp_const_servicename(snum));
8771         }
8772
8773 done:
8774         talloc_free(tmp_ctx);
8775         return status;
8776 }
8777
8778 /****************************************************************
8779  _spoolss_DeleteForm
8780 ****************************************************************/
8781
8782 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8783                            struct spoolss_DeleteForm *r)
8784 {
8785         const char *form_name = r->in.form_name;
8786         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8787         int snum = -1;
8788         WERROR status = WERR_OK;
8789         struct dcerpc_binding_handle *b;
8790         TALLOC_CTX *tmp_ctx = NULL;
8791
8792         DEBUG(5,("_spoolss_DeleteForm\n"));
8793
8794         if (!Printer) {
8795                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8796                         OUR_HANDLE(r->in.handle)));
8797                 return WERR_BADFID;
8798         }
8799
8800         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8801             !security_token_has_privilege(p->session_info->security_token,
8802                                           SEC_PRIV_PRINT_OPERATOR)) {
8803                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8804                 return WERR_ACCESS_DENIED;
8805         }
8806
8807         tmp_ctx = talloc_new(p->mem_ctx);
8808         if (!tmp_ctx) {
8809                 return WERR_NOMEM;
8810         }
8811
8812         status = winreg_printer_binding_handle(tmp_ctx,
8813                                                get_session_info_system(),
8814                                                p->msg_ctx,
8815                                                &b);
8816         if (!W_ERROR_IS_OK(status)) {
8817                 goto done;
8818         }
8819
8820         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8821         if (!W_ERROR_IS_OK(status)) {
8822                 goto done;
8823         }
8824
8825         /*
8826          * ChangeID must always be set if this is a printer
8827          */
8828         if (Printer->printer_type == SPLHND_PRINTER) {
8829                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8830                         status = WERR_BADFID;
8831                         goto done;
8832                 }
8833
8834                 status = winreg_printer_update_changeid(tmp_ctx, b,
8835                                                         lp_const_servicename(snum));
8836         }
8837
8838 done:
8839         talloc_free(tmp_ctx);
8840         return status;
8841 }
8842
8843 /****************************************************************
8844  _spoolss_SetForm
8845 ****************************************************************/
8846
8847 WERROR _spoolss_SetForm(struct pipes_struct *p,
8848                         struct spoolss_SetForm *r)
8849 {
8850         struct spoolss_AddFormInfo1 *form;
8851         const char *form_name = r->in.form_name;
8852         int snum = -1;
8853         WERROR status = WERR_OK;
8854         struct dcerpc_binding_handle *b;
8855         TALLOC_CTX *tmp_ctx = NULL;
8856
8857         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8858
8859         DEBUG(5,("_spoolss_SetForm\n"));
8860
8861         if (!Printer) {
8862                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8863                         OUR_HANDLE(r->in.handle)));
8864                 return WERR_BADFID;
8865         }
8866
8867         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8868            and not a printer admin, then fail */
8869
8870         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8871              !security_token_has_privilege(p->session_info->security_token,
8872                                            SEC_PRIV_PRINT_OPERATOR)) {
8873                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8874                 return WERR_ACCESS_DENIED;
8875         }
8876
8877         if (r->in.info_ctr->level != 1) {
8878                 return WERR_INVALID_LEVEL;
8879         }
8880
8881         form = r->in.info_ctr->info.info1;
8882         if (!form) {
8883                 return WERR_INVALID_PARAM;
8884         }
8885
8886         tmp_ctx = talloc_new(p->mem_ctx);
8887         if (!tmp_ctx) {
8888                 return WERR_NOMEM;
8889         }
8890
8891         status = winreg_printer_binding_handle(tmp_ctx,
8892                                                get_session_info_system(),
8893                                                p->msg_ctx,
8894                                                &b);
8895         if (!W_ERROR_IS_OK(status)) {
8896                 goto done;
8897         }
8898
8899         status = winreg_printer_setform1(tmp_ctx, b,
8900                                          form_name,
8901                                          form);
8902         if (!W_ERROR_IS_OK(status)) {
8903                 goto done;
8904         }
8905
8906         /*
8907          * ChangeID must always be set if this is a printer
8908          */
8909         if (Printer->printer_type == SPLHND_PRINTER) {
8910                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8911                         status = WERR_BADFID;
8912                         goto done;
8913                 }
8914
8915                 status = winreg_printer_update_changeid(tmp_ctx, b,
8916                                                         lp_const_servicename(snum));
8917         }
8918
8919 done:
8920         talloc_free(tmp_ctx);
8921         return status;
8922 }
8923
8924 /****************************************************************************
8925  fill_print_processor1
8926 ****************************************************************************/
8927
8928 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8929                                     struct spoolss_PrintProcessorInfo1 *r,
8930                                     const char *print_processor_name)
8931 {
8932         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8933         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8934
8935         return WERR_OK;
8936 }
8937
8938 /****************************************************************************
8939  enumprintprocessors level 1.
8940 ****************************************************************************/
8941
8942 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8943                                           union spoolss_PrintProcessorInfo **info_p,
8944                                           uint32_t *count)
8945 {
8946         union spoolss_PrintProcessorInfo *info;
8947         WERROR result;
8948
8949         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8950         W_ERROR_HAVE_NO_MEMORY(info);
8951
8952         *count = 1;
8953
8954         result = fill_print_processor1(info, &info[0].info1, "winprint");
8955         if (!W_ERROR_IS_OK(result)) {
8956                 goto out;
8957         }
8958
8959  out:
8960         if (!W_ERROR_IS_OK(result)) {
8961                 TALLOC_FREE(info);
8962                 *count = 0;
8963                 return result;
8964         }
8965
8966         *info_p = info;
8967
8968         return WERR_OK;
8969 }
8970
8971 /****************************************************************
8972  _spoolss_EnumPrintProcessors
8973 ****************************************************************/
8974
8975 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8976                                     struct spoolss_EnumPrintProcessors *r)
8977 {
8978         WERROR result;
8979
8980         /* that's an [in out] buffer */
8981
8982         if (!r->in.buffer && (r->in.offered != 0)) {
8983                 return WERR_INVALID_PARAM;
8984         }
8985
8986         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8987
8988         /*
8989          * Enumerate the print processors ...
8990          *
8991          * Just reply with "winprint", to keep NT happy
8992          * and I can use my nice printer checker.
8993          */
8994
8995         *r->out.count = 0;
8996         *r->out.needed = 0;
8997         *r->out.info = NULL;
8998
8999         if (!get_short_archi(r->in.environment)) {
9000                 return WERR_INVALID_ENVIRONMENT;
9001         }
9002
9003         switch (r->in.level) {
9004         case 1:
9005                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9006                                                      r->out.count);
9007                 break;
9008         default:
9009                 return WERR_UNKNOWN_LEVEL;
9010         }
9011
9012         if (!W_ERROR_IS_OK(result)) {
9013                 return result;
9014         }
9015
9016         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9017                                                      spoolss_EnumPrintProcessors,
9018                                                      *r->out.info, r->in.level,
9019                                                      *r->out.count);
9020         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9021         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9022
9023         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9024 }
9025
9026 /****************************************************************************
9027  fill_printprocdatatype1
9028 ****************************************************************************/
9029
9030 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9031                                       struct spoolss_PrintProcDataTypesInfo1 *r,
9032                                       const char *name_array)
9033 {
9034         r->name_array = talloc_strdup(mem_ctx, name_array);
9035         W_ERROR_HAVE_NO_MEMORY(r->name_array);
9036
9037         return WERR_OK;
9038 }
9039
9040 /****************************************************************************
9041  enumprintprocdatatypes level 1.
9042 ****************************************************************************/
9043
9044 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9045                                              union spoolss_PrintProcDataTypesInfo **info_p,
9046                                              uint32_t *count)
9047 {
9048         WERROR result;
9049         union spoolss_PrintProcDataTypesInfo *info;
9050
9051         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9052         W_ERROR_HAVE_NO_MEMORY(info);
9053
9054         *count = 1;
9055
9056         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9057         if (!W_ERROR_IS_OK(result)) {
9058                 goto out;
9059         }
9060
9061  out:
9062         if (!W_ERROR_IS_OK(result)) {
9063                 TALLOC_FREE(info);
9064                 *count = 0;
9065                 return result;
9066         }
9067
9068         *info_p = info;
9069
9070         return WERR_OK;
9071 }
9072
9073 /****************************************************************
9074  _spoolss_EnumPrintProcDataTypes
9075 ****************************************************************/
9076
9077 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9078                                        struct spoolss_EnumPrintProcDataTypes *r)
9079 {
9080         WERROR result;
9081
9082         /* that's an [in out] buffer */
9083
9084         if (!r->in.buffer && (r->in.offered != 0)) {
9085                 return WERR_INVALID_PARAM;
9086         }
9087
9088         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9089
9090         *r->out.count = 0;
9091         *r->out.needed = 0;
9092         *r->out.info = NULL;
9093
9094         if (r->in.print_processor_name == NULL ||
9095             !strequal(r->in.print_processor_name, "winprint")) {
9096                 return WERR_UNKNOWN_PRINTPROCESSOR;
9097         }
9098
9099         switch (r->in.level) {
9100         case 1:
9101                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9102                                                         r->out.count);
9103                 break;
9104         default:
9105                 return WERR_UNKNOWN_LEVEL;
9106         }
9107
9108         if (!W_ERROR_IS_OK(result)) {
9109                 return result;
9110         }
9111
9112         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9113                                                      spoolss_EnumPrintProcDataTypes,
9114                                                      *r->out.info, r->in.level,
9115                                                      *r->out.count);
9116         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9117         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9118
9119         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9120 }
9121
9122 /****************************************************************************
9123  fill_monitor_1
9124 ****************************************************************************/
9125
9126 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9127                              struct spoolss_MonitorInfo1 *r,
9128                              const char *monitor_name)
9129 {
9130         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9131         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9132
9133         return WERR_OK;
9134 }
9135
9136 /****************************************************************************
9137  fill_monitor_2
9138 ****************************************************************************/
9139
9140 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9141                              struct spoolss_MonitorInfo2 *r,
9142                              const char *monitor_name,
9143                              const char *environment,
9144                              const char *dll_name)
9145 {
9146         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9147         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9148         r->environment                  = talloc_strdup(mem_ctx, environment);
9149         W_ERROR_HAVE_NO_MEMORY(r->environment);
9150         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9151         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9152
9153         return WERR_OK;
9154 }
9155
9156 /****************************************************************************
9157  enumprintmonitors level 1.
9158 ****************************************************************************/
9159
9160 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9161                                         union spoolss_MonitorInfo **info_p,
9162                                         uint32_t *count)
9163 {
9164         union spoolss_MonitorInfo *info;
9165         WERROR result = WERR_OK;
9166
9167         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9168         W_ERROR_HAVE_NO_MEMORY(info);
9169
9170         *count = 2;
9171
9172         result = fill_monitor_1(info, &info[0].info1,
9173                                 SPL_LOCAL_PORT);
9174         if (!W_ERROR_IS_OK(result)) {
9175                 goto out;
9176         }
9177
9178         result = fill_monitor_1(info, &info[1].info1,
9179                                 SPL_TCPIP_PORT);
9180         if (!W_ERROR_IS_OK(result)) {
9181                 goto out;
9182         }
9183
9184 out:
9185         if (!W_ERROR_IS_OK(result)) {
9186                 TALLOC_FREE(info);
9187                 *count = 0;
9188                 return result;
9189         }
9190
9191         *info_p = info;
9192
9193         return WERR_OK;
9194 }
9195
9196 /****************************************************************************
9197  enumprintmonitors level 2.
9198 ****************************************************************************/
9199
9200 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9201                                         union spoolss_MonitorInfo **info_p,
9202                                         uint32_t *count)
9203 {
9204         union spoolss_MonitorInfo *info;
9205         WERROR result = WERR_OK;
9206
9207         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9208         W_ERROR_HAVE_NO_MEMORY(info);
9209
9210         *count = 2;
9211
9212         result = fill_monitor_2(info, &info[0].info2,
9213                                 SPL_LOCAL_PORT,
9214                                 "Windows NT X86", /* FIXME */
9215                                 "localmon.dll");
9216         if (!W_ERROR_IS_OK(result)) {
9217                 goto out;
9218         }
9219
9220         result = fill_monitor_2(info, &info[1].info2,
9221                                 SPL_TCPIP_PORT,
9222                                 "Windows NT X86", /* FIXME */
9223                                 "tcpmon.dll");
9224         if (!W_ERROR_IS_OK(result)) {
9225                 goto out;
9226         }
9227
9228 out:
9229         if (!W_ERROR_IS_OK(result)) {
9230                 TALLOC_FREE(info);
9231                 *count = 0;
9232                 return result;
9233         }
9234
9235         *info_p = info;
9236
9237         return WERR_OK;
9238 }
9239
9240 /****************************************************************
9241  _spoolss_EnumMonitors
9242 ****************************************************************/
9243
9244 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9245                              struct spoolss_EnumMonitors *r)
9246 {
9247         WERROR result;
9248
9249         /* that's an [in out] buffer */
9250
9251         if (!r->in.buffer && (r->in.offered != 0)) {
9252                 return WERR_INVALID_PARAM;
9253         }
9254
9255         DEBUG(5,("_spoolss_EnumMonitors\n"));
9256
9257         /*
9258          * Enumerate the print monitors ...
9259          *
9260          * Just reply with "Local Port", to keep NT happy
9261          * and I can use my nice printer checker.
9262          */
9263
9264         *r->out.count = 0;
9265         *r->out.needed = 0;
9266         *r->out.info = NULL;
9267
9268         switch (r->in.level) {
9269         case 1:
9270                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9271                                                    r->out.count);
9272                 break;
9273         case 2:
9274                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9275                                                    r->out.count);
9276                 break;
9277         default:
9278                 return WERR_UNKNOWN_LEVEL;
9279         }
9280
9281         if (!W_ERROR_IS_OK(result)) {
9282                 return result;
9283         }
9284
9285         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9286                                                      spoolss_EnumMonitors,
9287                                                      *r->out.info, r->in.level,
9288                                                      *r->out.count);
9289         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9290         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9291
9292         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9293 }
9294
9295 /****************************************************************************
9296 ****************************************************************************/
9297
9298 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9299                              const print_queue_struct *queue,
9300                              int count, int snum,
9301                              struct spoolss_PrinterInfo2 *pinfo2,
9302                              uint32_t jobid,
9303                              struct spoolss_JobInfo1 *r)
9304 {
9305         int i = 0;
9306         bool found = false;
9307
9308         for (i=0; i<count; i++) {
9309                 if (queue[i].sysjob == (int)jobid) {
9310                         found = true;
9311                         break;
9312                 }
9313         }
9314
9315         if (found == false) {
9316                 /* NT treats not found as bad param... yet another bad choice */
9317                 return WERR_INVALID_PARAM;
9318         }
9319
9320         return fill_job_info1(mem_ctx,
9321                               r,
9322                               &queue[i],
9323                               i,
9324                               snum,
9325                               pinfo2);
9326 }
9327
9328 /****************************************************************************
9329 ****************************************************************************/
9330
9331 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9332                              const print_queue_struct *queue,
9333                              int count, int snum,
9334                              struct spoolss_PrinterInfo2 *pinfo2,
9335                              uint32_t jobid,
9336                              struct spoolss_JobInfo2 *r)
9337 {
9338         int i = 0;
9339         bool found = false;
9340         struct spoolss_DeviceMode *devmode;
9341         WERROR result;
9342
9343         for (i=0; i<count; i++) {
9344                 if (queue[i].sysjob == (int)jobid) {
9345                         found = true;
9346                         break;
9347                 }
9348         }
9349
9350         if (found == false) {
9351                 /* NT treats not found as bad param... yet another bad
9352                    choice */
9353                 return WERR_INVALID_PARAM;
9354         }
9355
9356         /*
9357          * if the print job does not have a DEVMODE associated with it,
9358          * just use the one for the printer. A NULL devicemode is not
9359          *  a failure condition
9360          */
9361
9362         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9363         if (!devmode) {
9364                 result = spoolss_create_default_devmode(mem_ctx,
9365                                                 pinfo2->printername,
9366                                                 &devmode);
9367                 if (!W_ERROR_IS_OK(result)) {
9368                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9369                         return result;
9370                 }
9371         }
9372
9373         return fill_job_info2(mem_ctx,
9374                               r,
9375                               &queue[i],
9376                               i,
9377                               snum,
9378                               pinfo2,
9379                               devmode);
9380 }
9381
9382 /****************************************************************
9383  _spoolss_GetJob
9384 ****************************************************************/
9385
9386 WERROR _spoolss_GetJob(struct pipes_struct *p,
9387                        struct spoolss_GetJob *r)
9388 {
9389         WERROR result = WERR_OK;
9390         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9391         int snum;
9392         int count;
9393         print_queue_struct      *queue = NULL;
9394         print_status_struct prt_status;
9395
9396         /* that's an [in out] buffer */
9397
9398         if (!r->in.buffer && (r->in.offered != 0)) {
9399                 return WERR_INVALID_PARAM;
9400         }
9401
9402         DEBUG(5,("_spoolss_GetJob\n"));
9403
9404         *r->out.needed = 0;
9405
9406         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9407                 return WERR_BADFID;
9408         }
9409
9410         result = winreg_get_printer_internal(p->mem_ctx,
9411                                     get_session_info_system(),
9412                                     p->msg_ctx,
9413                                     lp_const_servicename(snum),
9414                                     &pinfo2);
9415         if (!W_ERROR_IS_OK(result)) {
9416                 return result;
9417         }
9418
9419         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9420
9421         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9422                      count, prt_status.status, prt_status.message));
9423
9424         switch (r->in.level) {
9425         case 1:
9426                 result = getjob_level_1(p->mem_ctx,
9427                                         queue, count, snum, pinfo2,
9428                                         r->in.job_id, &r->out.info->info1);
9429                 break;
9430         case 2:
9431                 result = getjob_level_2(p->mem_ctx,
9432                                         queue, count, snum, pinfo2,
9433                                         r->in.job_id, &r->out.info->info2);
9434                 break;
9435         default:
9436                 result = WERR_UNKNOWN_LEVEL;
9437                 break;
9438         }
9439
9440         SAFE_FREE(queue);
9441         TALLOC_FREE(pinfo2);
9442
9443         if (!W_ERROR_IS_OK(result)) {
9444                 TALLOC_FREE(r->out.info);
9445                 return result;
9446         }
9447
9448         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9449                                                                                    r->in.level);
9450         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9451
9452         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9453 }
9454
9455 /****************************************************************
9456  _spoolss_GetPrinterDataEx
9457 ****************************************************************/
9458
9459 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9460                                  struct spoolss_GetPrinterDataEx *r)
9461 {
9462
9463         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9464         const char *printer;
9465         int                     snum = 0;
9466         WERROR result = WERR_OK;
9467         DATA_BLOB blob;
9468         enum winreg_Type val_type = REG_NONE;
9469         uint8_t *val_data = NULL;
9470         uint32_t val_size = 0;
9471         struct dcerpc_binding_handle *b;
9472         TALLOC_CTX *tmp_ctx;
9473
9474         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9475
9476         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9477                 r->in.key_name, r->in.value_name));
9478
9479         /* in case of problem, return some default values */
9480
9481         *r->out.needed  = 0;
9482         *r->out.type    = REG_NONE;
9483
9484         tmp_ctx = talloc_new(p->mem_ctx);
9485         if (!tmp_ctx) {
9486                 return WERR_NOMEM;
9487         }
9488
9489         if (!Printer) {
9490                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9491                         OUR_HANDLE(r->in.handle)));
9492                 result = WERR_BADFID;
9493                 goto done;
9494         }
9495
9496         /* check to see if the keyname is valid */
9497         if (!strlen(r->in.key_name)) {
9498                 result = WERR_INVALID_PARAM;
9499                 goto done;
9500         }
9501
9502         /* Is the handle to a printer or to the server? */
9503
9504         if (Printer->printer_type == SPLHND_SERVER) {
9505
9506                 union spoolss_PrinterData data;
9507
9508                 result = getprinterdata_printer_server(tmp_ctx,
9509                                                        r->in.value_name,
9510                                                        r->out.type,
9511                                                        &data);
9512                 if (!W_ERROR_IS_OK(result)) {
9513                         goto done;
9514                 }
9515
9516                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9517                                                   *r->out.type, &data);
9518                 if (!W_ERROR_IS_OK(result)) {
9519                         goto done;
9520                 }
9521
9522                 *r->out.needed = blob.length;
9523
9524                 if (r->in.offered >= *r->out.needed) {
9525                         memcpy(r->out.data, blob.data, blob.length);
9526                 }
9527
9528                 result = WERR_OK;
9529                 goto done;
9530         }
9531
9532         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9533                 result = WERR_BADFID;
9534                 goto done;
9535         }
9536         printer = lp_const_servicename(snum);
9537
9538         result = winreg_printer_binding_handle(tmp_ctx,
9539                                                get_session_info_system(),
9540                                                p->msg_ctx,
9541                                                &b);
9542         if (!W_ERROR_IS_OK(result)) {
9543                 goto done;
9544         }
9545
9546         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9547         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9548             strequal(r->in.value_name, "ChangeId")) {
9549                 *r->out.type = REG_DWORD;
9550                 *r->out.needed = 4;
9551                 if (r->in.offered >= *r->out.needed) {
9552                         uint32_t changeid = 0;
9553
9554                         result = winreg_printer_get_changeid(tmp_ctx, b,
9555                                                              printer,
9556                                                              &changeid);
9557                         if (!W_ERROR_IS_OK(result)) {
9558                                 goto done;
9559                         }
9560
9561                         SIVAL(r->out.data, 0, changeid);
9562                         result = WERR_OK;
9563                 }
9564                 goto done;
9565         }
9566
9567         result = winreg_get_printer_dataex(tmp_ctx, b,
9568                                            printer,
9569                                            r->in.key_name,
9570                                            r->in.value_name,
9571                                            &val_type,
9572                                            &val_data,
9573                                            &val_size);
9574         if (!W_ERROR_IS_OK(result)) {
9575                 goto done;
9576         }
9577
9578         *r->out.needed = val_size;
9579         *r->out.type = val_type;
9580
9581         if (r->in.offered >= *r->out.needed) {
9582                 memcpy(r->out.data, val_data, val_size);
9583         }
9584
9585 done:
9586         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9587
9588         if (W_ERROR_IS_OK(result)) {
9589                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9590         }
9591
9592         talloc_free(tmp_ctx);
9593         return result;
9594 }
9595
9596 /****************************************************************
9597  _spoolss_SetPrinterDataEx
9598 ****************************************************************/
9599
9600 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9601                                  struct spoolss_SetPrinterDataEx *r)
9602 {
9603         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9604         int                     snum = 0;
9605         WERROR                  result = WERR_OK;
9606         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9607         char                    *oid_string;
9608         struct dcerpc_binding_handle *b;
9609         TALLOC_CTX *tmp_ctx;
9610
9611         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9612
9613         /* From MSDN documentation of SetPrinterDataEx: pass request to
9614            SetPrinterData if key is "PrinterDriverData" */
9615
9616         if (!Printer) {
9617                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9618                         OUR_HANDLE(r->in.handle)));
9619                 return WERR_BADFID;
9620         }
9621
9622         if (Printer->printer_type == SPLHND_SERVER) {
9623                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9624                         "Not implemented for server handles yet\n"));
9625                 return WERR_INVALID_PARAM;
9626         }
9627
9628         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9629                 return WERR_BADFID;
9630         }
9631
9632         /*
9633          * Access check : NT returns "access denied" if you make a
9634          * SetPrinterData call without the necessary privildge.
9635          * we were originally returning OK if nothing changed
9636          * which made Win2k issue **a lot** of SetPrinterData
9637          * when connecting to a printer  --jerry
9638          */
9639
9640         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9641                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9642                         "change denied by handle access permissions\n"));
9643                 return WERR_ACCESS_DENIED;
9644         }
9645
9646         tmp_ctx = talloc_new(p->mem_ctx);
9647         if (!tmp_ctx) {
9648                 return WERR_NOMEM;
9649         }
9650
9651         result = winreg_printer_binding_handle(tmp_ctx,
9652                                                get_session_info_system(),
9653                                                p->msg_ctx,
9654                                                &b);
9655         if (!W_ERROR_IS_OK(result)) {
9656                 goto done;
9657         }
9658
9659         result = winreg_get_printer(tmp_ctx, b,
9660                                     lp_servicename(talloc_tos(), snum),
9661                                     &pinfo2);
9662         if (!W_ERROR_IS_OK(result)) {
9663                 goto done;
9664         }
9665
9666         /* check for OID in valuename */
9667
9668         oid_string = strchr(r->in.value_name, ',');
9669         if (oid_string) {
9670                 *oid_string = '\0';
9671                 oid_string++;
9672         }
9673
9674         /* save the registry data */
9675
9676         result = winreg_set_printer_dataex(tmp_ctx, b,
9677                                            pinfo2->sharename,
9678                                            r->in.key_name,
9679                                            r->in.value_name,
9680                                            r->in.type,
9681                                            r->in.data,
9682                                            r->in.offered);
9683
9684         if (W_ERROR_IS_OK(result)) {
9685                 /* save the OID if one was specified */
9686                 if (oid_string) {
9687                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9688                                 r->in.key_name, SPOOL_OID_KEY);
9689                         if (!str) {
9690                                 result = WERR_NOMEM;
9691                                 goto done;
9692                         }
9693
9694                         /*
9695                          * I'm not checking the status here on purpose.  Don't know
9696                          * if this is right, but I'm returning the status from the
9697                          * previous set_printer_dataex() call.  I have no idea if
9698                          * this is right.    --jerry
9699                          */
9700                         winreg_set_printer_dataex(tmp_ctx, b,
9701                                                   pinfo2->sharename,
9702                                                   str,
9703                                                   r->in.value_name,
9704                                                   REG_SZ,
9705                                                   (uint8_t *) oid_string,
9706                                                   strlen(oid_string) + 1);
9707                 }
9708
9709                 result = winreg_printer_update_changeid(tmp_ctx, b,
9710                                                         lp_const_servicename(snum));
9711
9712         }
9713
9714 done:
9715         talloc_free(tmp_ctx);
9716         return result;
9717 }
9718
9719 /****************************************************************
9720  _spoolss_DeletePrinterDataEx
9721 ****************************************************************/
9722
9723 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9724                                     struct spoolss_DeletePrinterDataEx *r)
9725 {
9726         const char *printer;
9727         int             snum=0;
9728         WERROR          status = WERR_OK;
9729         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9730
9731         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9732
9733         if (!Printer) {
9734                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9735                         "Invalid handle (%s:%u:%u).\n",
9736                         OUR_HANDLE(r->in.handle)));
9737                 return WERR_BADFID;
9738         }
9739
9740         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9741                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9742                         "printer properties change denied by handle\n"));
9743                 return WERR_ACCESS_DENIED;
9744         }
9745
9746         if (!r->in.value_name || !r->in.key_name) {
9747                 return WERR_NOMEM;
9748         }
9749
9750         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9751                 return WERR_BADFID;
9752         }
9753         printer = lp_const_servicename(snum);
9754
9755         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9756                                               get_session_info_system(),
9757                                               p->msg_ctx,
9758                                               printer,
9759                                               r->in.key_name,
9760                                               r->in.value_name);
9761         if (W_ERROR_IS_OK(status)) {
9762                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9763                                                         get_session_info_system(),
9764                                                         p->msg_ctx,
9765                                                         printer);
9766         }
9767
9768         return status;
9769 }
9770
9771 /****************************************************************
9772  _spoolss_EnumPrinterKey
9773 ****************************************************************/
9774
9775 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9776                                struct spoolss_EnumPrinterKey *r)
9777 {
9778         uint32_t        num_keys;
9779         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9780         int             snum = 0;
9781         WERROR          result = WERR_BADFILE;
9782         const char **array = NULL;
9783         DATA_BLOB blob;
9784
9785         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9786
9787         if (!Printer) {
9788                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9789                         OUR_HANDLE(r->in.handle)));
9790                 return WERR_BADFID;
9791         }
9792
9793         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9794                 return WERR_BADFID;
9795         }
9796
9797         result = winreg_enum_printer_key_internal(p->mem_ctx,
9798                                          get_session_info_system(),
9799                                          p->msg_ctx,
9800                                          lp_const_servicename(snum),
9801                                          r->in.key_name,
9802                                          &num_keys,
9803                                          &array);
9804         if (!W_ERROR_IS_OK(result)) {
9805                 goto done;
9806         }
9807
9808         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9809                 result = WERR_NOMEM;
9810                 goto done;
9811         }
9812
9813         *r->out._ndr_size = r->in.offered / 2;
9814         *r->out.needed = blob.length;
9815
9816         if (r->in.offered < *r->out.needed) {
9817                 result = WERR_MORE_DATA;
9818         } else {
9819                 result = WERR_OK;
9820                 r->out.key_buffer->string_array = array;
9821         }
9822
9823  done:
9824         if (!W_ERROR_IS_OK(result)) {
9825                 TALLOC_FREE(array);
9826                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9827                         *r->out.needed = 0;
9828                 }
9829         }
9830
9831         return result;
9832 }
9833
9834 /****************************************************************
9835  _spoolss_DeletePrinterKey
9836 ****************************************************************/
9837
9838 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9839                                  struct spoolss_DeletePrinterKey *r)
9840 {
9841         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9842         int                     snum=0;
9843         WERROR                  status;
9844         const char *printer;
9845         struct dcerpc_binding_handle *b;
9846         TALLOC_CTX *tmp_ctx;
9847
9848         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9849
9850         if (!Printer) {
9851                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9852                         OUR_HANDLE(r->in.handle)));
9853                 return WERR_BADFID;
9854         }
9855
9856         /* if keyname == NULL, return error */
9857         if ( !r->in.key_name )
9858                 return WERR_INVALID_PARAM;
9859
9860         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9861                 return WERR_BADFID;
9862         }
9863
9864         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9865                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9866                         "printer properties change denied by handle\n"));
9867                 return WERR_ACCESS_DENIED;
9868         }
9869
9870         printer = lp_const_servicename(snum);
9871
9872         tmp_ctx = talloc_new(p->mem_ctx);
9873         if (!tmp_ctx) {
9874                 return WERR_NOMEM;
9875         }
9876
9877         status = winreg_printer_binding_handle(tmp_ctx,
9878                                                get_session_info_system(),
9879                                                p->msg_ctx,
9880                                                &b);
9881         if (!W_ERROR_IS_OK(status)) {
9882                 goto done;
9883         }
9884
9885         /* delete the key and all subkeys */
9886         status = winreg_delete_printer_key(tmp_ctx, b,
9887                                            printer,
9888                                            r->in.key_name);
9889         if (W_ERROR_IS_OK(status)) {
9890                 status = winreg_printer_update_changeid(tmp_ctx, b,
9891                                                         printer);
9892         }
9893
9894 done:
9895         talloc_free(tmp_ctx);
9896         return status;
9897 }
9898
9899 /****************************************************************
9900  _spoolss_EnumPrinterDataEx
9901 ****************************************************************/
9902
9903 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9904                                   struct spoolss_EnumPrinterDataEx *r)
9905 {
9906         uint32_t        count = 0;
9907         struct spoolss_PrinterEnumValues *info = NULL;
9908         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9909         int             snum;
9910         WERROR          result;
9911
9912         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9913
9914         *r->out.count = 0;
9915         *r->out.needed = 0;
9916         *r->out.info = NULL;
9917
9918         if (!Printer) {
9919                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9920                         OUR_HANDLE(r->in.handle)));
9921                 return WERR_BADFID;
9922         }
9923
9924         /*
9925          * first check for a keyname of NULL or "".  Win2k seems to send
9926          * this a lot and we should send back WERR_INVALID_PARAM
9927          * no need to spend time looking up the printer in this case.
9928          * --jerry
9929          */
9930
9931         if (!strlen(r->in.key_name)) {
9932                 result = WERR_INVALID_PARAM;
9933                 goto done;
9934         }
9935
9936         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9937                 return WERR_BADFID;
9938         }
9939
9940         /* now look for a match on the key name */
9941         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9942                                             get_session_info_system(),
9943                                             p->msg_ctx,
9944                                             lp_const_servicename(snum),
9945                                             r->in.key_name,
9946                                             &count,
9947                                             &info);
9948         if (!W_ERROR_IS_OK(result)) {
9949                 goto done;
9950         }
9951
9952 #if 0 /* FIXME - gd */
9953         /* housekeeping information in the reply */
9954
9955         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9956          * the hand marshalled container size is a multiple
9957          * of 4 bytes for RPC alignment.
9958          */
9959
9960         if (needed % 4) {
9961                 needed += 4-(needed % 4);
9962         }
9963 #endif
9964         *r->out.count   = count;
9965         *r->out.info    = info;
9966
9967  done:
9968         if (!W_ERROR_IS_OK(result)) {
9969                 return result;
9970         }
9971
9972         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9973                                                spoolss_EnumPrinterDataEx,
9974                                                *r->out.info,
9975                                                *r->out.count);
9976         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9977         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9978
9979         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9980 }
9981
9982 /****************************************************************************
9983 ****************************************************************************/
9984
9985 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9986                                                  const char *servername,
9987                                                  const char *environment,
9988                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9989 {
9990         WERROR werr;
9991         char *path = NULL;
9992
9993         werr = compose_spoolss_server_path(mem_ctx,
9994                                            servername,
9995                                            environment,
9996                                            SPOOLSS_PRTPROCS_PATH,
9997                                            &path);
9998         if (!W_ERROR_IS_OK(werr)) {
9999                 return werr;
10000         }
10001
10002         DEBUG(4,("print processor directory: [%s]\n", path));
10003
10004         r->directory_name = path;
10005
10006         return WERR_OK;
10007 }
10008
10009 /****************************************************************
10010  _spoolss_GetPrintProcessorDirectory
10011 ****************************************************************/
10012
10013 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10014                                            struct spoolss_GetPrintProcessorDirectory *r)
10015 {
10016         WERROR result;
10017         char *prnproc_share = NULL;
10018         bool prnproc_share_exists = false;
10019         int snum;
10020
10021         /* that's an [in out] buffer */
10022
10023         if (!r->in.buffer && (r->in.offered != 0)) {
10024                 return WERR_INVALID_PARAM;
10025         }
10026
10027         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10028                 r->in.level));
10029
10030         *r->out.needed = 0;
10031
10032         /* r->in.level is ignored */
10033
10034         /* We always should reply with a local print processor directory so that
10035          * users are not forced to have a [prnproc$] share on the Samba spoolss
10036          * server, if users decide to do so, lets announce it though - Guenther */
10037
10038         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10039         if (!prnproc_share) {
10040                 return WERR_NOMEM;
10041         }
10042         if (snum != -1) {
10043                 prnproc_share_exists = true;
10044         }
10045
10046         result = getprintprocessordirectory_level_1(p->mem_ctx,
10047                                                     prnproc_share_exists ? r->in.server : NULL,
10048                                                     r->in.environment,
10049                                                     &r->out.info->info1);
10050         if (!W_ERROR_IS_OK(result)) {
10051                 TALLOC_FREE(r->out.info);
10052                 return result;
10053         }
10054
10055         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10056                                                                                    r->out.info, r->in.level);
10057         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10058
10059         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10060 }
10061
10062 /*******************************************************************
10063  ********************************************************************/
10064
10065 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10066                                const char *dllname)
10067 {
10068         enum ndr_err_code ndr_err;
10069         struct spoolss_MonitorUi ui;
10070
10071         ui.dll_name = dllname;
10072
10073         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10074                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10075         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10076                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10077         }
10078         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10079 }
10080
10081 /*******************************************************************
10082  Streams the monitor UI DLL name in UNICODE
10083 *******************************************************************/
10084
10085 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10086                                struct security_token *token, DATA_BLOB *in,
10087                                DATA_BLOB *out, uint32_t *needed)
10088 {
10089         const char *dllname = "tcpmonui.dll";
10090
10091         *needed = (strlen(dllname)+1) * 2;
10092
10093         if (out->length < *needed) {
10094                 return WERR_INSUFFICIENT_BUFFER;
10095         }
10096
10097         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10098                 return WERR_NOMEM;
10099         }
10100
10101         return WERR_OK;
10102 }
10103
10104 /*******************************************************************
10105  ********************************************************************/
10106
10107 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10108                              struct spoolss_PortData1 *port1,
10109                              const DATA_BLOB *buf)
10110 {
10111         enum ndr_err_code ndr_err;
10112         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10113                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10114         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10115                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10116         }
10117         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10118 }
10119
10120 /*******************************************************************
10121  ********************************************************************/
10122
10123 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10124                              struct spoolss_PortData2 *port2,
10125                              const DATA_BLOB *buf)
10126 {
10127         enum ndr_err_code ndr_err;
10128         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10129                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10130         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10131                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10132         }
10133         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10134 }
10135
10136 /*******************************************************************
10137  Create a new TCP/IP port
10138 *******************************************************************/
10139
10140 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10141                              struct security_token *token, DATA_BLOB *in,
10142                              DATA_BLOB *out, uint32_t *needed)
10143 {
10144         struct spoolss_PortData1 port1;
10145         struct spoolss_PortData2 port2;
10146         char *device_uri = NULL;
10147         uint32_t version;
10148
10149         const char *portname;
10150         const char *hostaddress;
10151         const char *queue;
10152         uint32_t port_number;
10153         uint32_t protocol;
10154
10155         /* peek for spoolss_PortData version */
10156
10157         if (!in || (in->length < (128 + 4))) {
10158                 return WERR_GENERAL_FAILURE;
10159         }
10160
10161         version = IVAL(in->data, 128);
10162
10163         switch (version) {
10164                 case 1:
10165                         ZERO_STRUCT(port1);
10166
10167                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10168                                 return WERR_NOMEM;
10169                         }
10170
10171                         portname        = port1.portname;
10172                         hostaddress     = port1.hostaddress;
10173                         queue           = port1.queue;
10174                         protocol        = port1.protocol;
10175                         port_number     = port1.port_number;
10176
10177                         break;
10178                 case 2:
10179                         ZERO_STRUCT(port2);
10180
10181                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10182                                 return WERR_NOMEM;
10183                         }
10184
10185                         portname        = port2.portname;
10186                         hostaddress     = port2.hostaddress;
10187                         queue           = port2.queue;
10188                         protocol        = port2.protocol;
10189                         port_number     = port2.port_number;
10190
10191                         break;
10192                 default:
10193                         DEBUG(1,("xcvtcp_addport: "
10194                                 "unknown version of port_data: %d\n", version));
10195                         return WERR_UNKNOWN_PORT;
10196         }
10197
10198         /* create the device URI and call the add_port_hook() */
10199
10200         switch (protocol) {
10201         case PROTOCOL_RAWTCP_TYPE:
10202                 device_uri = talloc_asprintf(mem_ctx,
10203                                 "socket://%s:%d/", hostaddress,
10204                                 port_number);
10205                 break;
10206
10207         case PROTOCOL_LPR_TYPE:
10208                 device_uri = talloc_asprintf(mem_ctx,
10209                         "lpr://%s/%s", hostaddress, queue );
10210                 break;
10211
10212         default:
10213                 return WERR_UNKNOWN_PORT;
10214         }
10215
10216         if (!device_uri) {
10217                 return WERR_NOMEM;
10218         }
10219
10220         return add_port_hook(mem_ctx, token, portname, device_uri);
10221 }
10222
10223 /*******************************************************************
10224 *******************************************************************/
10225
10226 struct xcv_api_table xcvtcp_cmds[] = {
10227         { "MonitorUI",  xcvtcp_monitorui },
10228         { "AddPort",    xcvtcp_addport},
10229         { NULL,         NULL }
10230 };
10231
10232 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10233                                      struct security_token *token, const char *command,
10234                                      DATA_BLOB *inbuf,
10235                                      DATA_BLOB *outbuf,
10236                                      uint32_t *needed )
10237 {
10238         int i;
10239
10240         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10241
10242         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10243                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10244                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10245         }
10246
10247         return WERR_BADFUNC;
10248 }
10249
10250 /*******************************************************************
10251 *******************************************************************/
10252 #if 0   /* don't support management using the "Local Port" monitor */
10253
10254 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10255                                  struct security_token *token, DATA_BLOB *in,
10256                                  DATA_BLOB *out, uint32_t *needed)
10257 {
10258         const char *dllname = "localui.dll";
10259
10260         *needed = (strlen(dllname)+1) * 2;
10261
10262         if (out->length < *needed) {
10263                 return WERR_INSUFFICIENT_BUFFER;
10264         }
10265
10266         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10267                 return WERR_NOMEM;
10268         }
10269
10270         return WERR_OK;
10271 }
10272
10273 /*******************************************************************
10274 *******************************************************************/
10275
10276 struct xcv_api_table xcvlocal_cmds[] = {
10277         { "MonitorUI",  xcvlocal_monitorui },
10278         { NULL,         NULL }
10279 };
10280 #else
10281 struct xcv_api_table xcvlocal_cmds[] = {
10282         { NULL,         NULL }
10283 };
10284 #endif
10285
10286
10287
10288 /*******************************************************************
10289 *******************************************************************/
10290
10291 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10292                                        struct security_token *token, const char *command,
10293                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10294                                        uint32_t *needed)
10295 {
10296         int i;
10297
10298         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10299
10300         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10301                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10302                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10303         }
10304         return WERR_BADFUNC;
10305 }
10306
10307 /****************************************************************
10308  _spoolss_XcvData
10309 ****************************************************************/
10310
10311 WERROR _spoolss_XcvData(struct pipes_struct *p,
10312                         struct spoolss_XcvData *r)
10313 {
10314         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10315         DATA_BLOB out_data = data_blob_null;
10316         WERROR werror;
10317
10318         if (!Printer) {
10319                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10320                         OUR_HANDLE(r->in.handle)));
10321                 return WERR_BADFID;
10322         }
10323
10324         /* Has to be a handle to the TCP/IP port monitor */
10325
10326         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10327                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10328                 return WERR_BADFID;
10329         }
10330
10331         /* requires administrative access to the server */
10332
10333         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10334                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10335                 return WERR_ACCESS_DENIED;
10336         }
10337
10338         /* Allocate the outgoing buffer */
10339
10340         if (r->in.out_data_size) {
10341                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10342                 if (out_data.data == NULL) {
10343                         return WERR_NOMEM;
10344                 }
10345         }
10346
10347         switch ( Printer->printer_type ) {
10348         case SPLHND_PORTMON_TCP:
10349                 werror = process_xcvtcp_command(p->mem_ctx,
10350                                                 p->session_info->security_token,
10351                                                 r->in.function_name,
10352                                                 &r->in.in_data, &out_data,
10353                                                 r->out.needed);
10354                 break;
10355         case SPLHND_PORTMON_LOCAL:
10356                 werror = process_xcvlocal_command(p->mem_ctx,
10357                                                   p->session_info->security_token,
10358                                                   r->in.function_name,
10359                                                   &r->in.in_data, &out_data,
10360                                                   r->out.needed);
10361                 break;
10362         default:
10363                 werror = WERR_INVALID_PRINT_MONITOR;
10364         }
10365
10366         if (!W_ERROR_IS_OK(werror)) {
10367                 return werror;
10368         }
10369
10370         *r->out.status_code = 0;
10371
10372         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10373                 memcpy(r->out.out_data, out_data.data,
10374                         MIN(r->in.out_data_size, out_data.length));
10375         }
10376
10377         return WERR_OK;
10378 }
10379
10380 /****************************************************************
10381  _spoolss_AddPrintProcessor
10382 ****************************************************************/
10383
10384 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10385                                   struct spoolss_AddPrintProcessor *r)
10386 {
10387         /* for now, just indicate success and ignore the add.  We'll
10388            automatically set the winprint processor for printer
10389            entries later.  Used to debug the LexMark Optra S 1855 PCL
10390            driver --jerry */
10391
10392         return WERR_OK;
10393 }
10394
10395 /****************************************************************
10396  _spoolss_AddPort
10397 ****************************************************************/
10398
10399 WERROR _spoolss_AddPort(struct pipes_struct *p,
10400                         struct spoolss_AddPort *r)
10401 {
10402         /* do what w2k3 does */
10403
10404         return WERR_NOT_SUPPORTED;
10405 }
10406
10407 /****************************************************************
10408  _spoolss_GetPrinterDriver
10409 ****************************************************************/
10410
10411 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10412                                  struct spoolss_GetPrinterDriver *r)
10413 {
10414         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10415         return WERR_NOT_SUPPORTED;
10416 }
10417
10418 /****************************************************************
10419  _spoolss_ReadPrinter
10420 ****************************************************************/
10421
10422 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10423                             struct spoolss_ReadPrinter *r)
10424 {
10425         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10426         return WERR_NOT_SUPPORTED;
10427 }
10428
10429 /****************************************************************
10430  _spoolss_WaitForPrinterChange
10431 ****************************************************************/
10432
10433 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10434                                      struct spoolss_WaitForPrinterChange *r)
10435 {
10436         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10437         return WERR_NOT_SUPPORTED;
10438 }
10439
10440 /****************************************************************
10441  _spoolss_ConfigurePort
10442 ****************************************************************/
10443
10444 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10445                               struct spoolss_ConfigurePort *r)
10446 {
10447         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10448         return WERR_NOT_SUPPORTED;
10449 }
10450
10451 /****************************************************************
10452  _spoolss_DeletePort
10453 ****************************************************************/
10454
10455 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10456                            struct spoolss_DeletePort *r)
10457 {
10458         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10459         return WERR_NOT_SUPPORTED;
10460 }
10461
10462 /****************************************************************
10463  _spoolss_CreatePrinterIC
10464 ****************************************************************/
10465
10466 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10467                                 struct spoolss_CreatePrinterIC *r)
10468 {
10469         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10470         return WERR_NOT_SUPPORTED;
10471 }
10472
10473 /****************************************************************
10474  _spoolss_PlayGDIScriptOnPrinterIC
10475 ****************************************************************/
10476
10477 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10478                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10479 {
10480         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10481         return WERR_NOT_SUPPORTED;
10482 }
10483
10484 /****************************************************************
10485  _spoolss_DeletePrinterIC
10486 ****************************************************************/
10487
10488 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10489                                 struct spoolss_DeletePrinterIC *r)
10490 {
10491         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10492         return WERR_NOT_SUPPORTED;
10493 }
10494
10495 /****************************************************************
10496  _spoolss_AddPrinterConnection
10497 ****************************************************************/
10498
10499 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10500                                      struct spoolss_AddPrinterConnection *r)
10501 {
10502         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10503         return WERR_NOT_SUPPORTED;
10504 }
10505
10506 /****************************************************************
10507  _spoolss_DeletePrinterConnection
10508 ****************************************************************/
10509
10510 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10511                                         struct spoolss_DeletePrinterConnection *r)
10512 {
10513         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10514         return WERR_NOT_SUPPORTED;
10515 }
10516
10517 /****************************************************************
10518  _spoolss_PrinterMessageBox
10519 ****************************************************************/
10520
10521 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10522                                   struct spoolss_PrinterMessageBox *r)
10523 {
10524         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10525         return WERR_NOT_SUPPORTED;
10526 }
10527
10528 /****************************************************************
10529  _spoolss_AddMonitor
10530 ****************************************************************/
10531
10532 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10533                            struct spoolss_AddMonitor *r)
10534 {
10535         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10536         return WERR_NOT_SUPPORTED;
10537 }
10538
10539 /****************************************************************
10540  _spoolss_DeleteMonitor
10541 ****************************************************************/
10542
10543 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10544                               struct spoolss_DeleteMonitor *r)
10545 {
10546         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10547         return WERR_NOT_SUPPORTED;
10548 }
10549
10550 /****************************************************************
10551  _spoolss_DeletePrintProcessor
10552 ****************************************************************/
10553
10554 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10555                                      struct spoolss_DeletePrintProcessor *r)
10556 {
10557         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10558         return WERR_NOT_SUPPORTED;
10559 }
10560
10561 /****************************************************************
10562  _spoolss_AddPrintProvidor
10563 ****************************************************************/
10564
10565 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10566                                  struct spoolss_AddPrintProvidor *r)
10567 {
10568         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10569         return WERR_NOT_SUPPORTED;
10570 }
10571
10572 /****************************************************************
10573  _spoolss_DeletePrintProvidor
10574 ****************************************************************/
10575
10576 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10577                                     struct spoolss_DeletePrintProvidor *r)
10578 {
10579         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10580         return WERR_NOT_SUPPORTED;
10581 }
10582
10583 /****************************************************************
10584  _spoolss_FindFirstPrinterChangeNotification
10585 ****************************************************************/
10586
10587 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10588                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10589 {
10590         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10591         return WERR_NOT_SUPPORTED;
10592 }
10593
10594 /****************************************************************
10595  _spoolss_FindNextPrinterChangeNotification
10596 ****************************************************************/
10597
10598 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10599                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10600 {
10601         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10602         return WERR_NOT_SUPPORTED;
10603 }
10604
10605 /****************************************************************
10606  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10607 ****************************************************************/
10608
10609 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10610                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10611 {
10612         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10613         return WERR_NOT_SUPPORTED;
10614 }
10615
10616 /****************************************************************
10617  _spoolss_ReplyOpenPrinter
10618 ****************************************************************/
10619
10620 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10621                                  struct spoolss_ReplyOpenPrinter *r)
10622 {
10623         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10624         return WERR_NOT_SUPPORTED;
10625 }
10626
10627 /****************************************************************
10628  _spoolss_RouterReplyPrinter
10629 ****************************************************************/
10630
10631 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10632                                    struct spoolss_RouterReplyPrinter *r)
10633 {
10634         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10635         return WERR_NOT_SUPPORTED;
10636 }
10637
10638 /****************************************************************
10639  _spoolss_ReplyClosePrinter
10640 ****************************************************************/
10641
10642 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10643                                   struct spoolss_ReplyClosePrinter *r)
10644 {
10645         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10646         return WERR_NOT_SUPPORTED;
10647 }
10648
10649 /****************************************************************
10650  _spoolss_AddPortEx
10651 ****************************************************************/
10652
10653 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10654                           struct spoolss_AddPortEx *r)
10655 {
10656         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10657         return WERR_NOT_SUPPORTED;
10658 }
10659
10660 /****************************************************************
10661  _spoolss_RouterFindFirstPrinterChangeNotification
10662 ****************************************************************/
10663
10664 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10665                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10666 {
10667         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10668         return WERR_NOT_SUPPORTED;
10669 }
10670
10671 /****************************************************************
10672  _spoolss_SpoolerInit
10673 ****************************************************************/
10674
10675 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10676                             struct spoolss_SpoolerInit *r)
10677 {
10678         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10679         return WERR_NOT_SUPPORTED;
10680 }
10681
10682 /****************************************************************
10683  _spoolss_ResetPrinterEx
10684 ****************************************************************/
10685
10686 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10687                                struct spoolss_ResetPrinterEx *r)
10688 {
10689         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10690         return WERR_NOT_SUPPORTED;
10691 }
10692
10693 /****************************************************************
10694  _spoolss_RouterReplyPrinterEx
10695 ****************************************************************/
10696
10697 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10698                                      struct spoolss_RouterReplyPrinterEx *r)
10699 {
10700         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10701         return WERR_NOT_SUPPORTED;
10702 }
10703
10704 /****************************************************************
10705  _spoolss_44
10706 ****************************************************************/
10707
10708 WERROR _spoolss_44(struct pipes_struct *p,
10709                    struct spoolss_44 *r)
10710 {
10711         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10712         return WERR_NOT_SUPPORTED;
10713 }
10714
10715 /****************************************************************
10716  _spoolss_SetPort
10717 ****************************************************************/
10718
10719 WERROR _spoolss_SetPort(struct pipes_struct *p,
10720                         struct spoolss_SetPort *r)
10721 {
10722         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10723         return WERR_NOT_SUPPORTED;
10724 }
10725
10726 /****************************************************************
10727  _spoolss_4a
10728 ****************************************************************/
10729
10730 WERROR _spoolss_4a(struct pipes_struct *p,
10731                    struct spoolss_4a *r)
10732 {
10733         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10734         return WERR_NOT_SUPPORTED;
10735 }
10736
10737 /****************************************************************
10738  _spoolss_4b
10739 ****************************************************************/
10740
10741 WERROR _spoolss_4b(struct pipes_struct *p,
10742                    struct spoolss_4b *r)
10743 {
10744         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10745         return WERR_NOT_SUPPORTED;
10746 }
10747
10748 /****************************************************************
10749  _spoolss_4c
10750 ****************************************************************/
10751
10752 WERROR _spoolss_4c(struct pipes_struct *p,
10753                    struct spoolss_4c *r)
10754 {
10755         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10756         return WERR_NOT_SUPPORTED;
10757 }
10758
10759 /****************************************************************
10760  _spoolss_53
10761 ****************************************************************/
10762
10763 WERROR _spoolss_53(struct pipes_struct *p,
10764                    struct spoolss_53 *r)
10765 {
10766         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10767         return WERR_NOT_SUPPORTED;
10768 }
10769
10770 /****************************************************************
10771  _spoolss_AddPerMachineConnection
10772 ****************************************************************/
10773
10774 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10775                                         struct spoolss_AddPerMachineConnection *r)
10776 {
10777         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10778         return WERR_NOT_SUPPORTED;
10779 }
10780
10781 /****************************************************************
10782  _spoolss_DeletePerMachineConnection
10783 ****************************************************************/
10784
10785 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10786                                            struct spoolss_DeletePerMachineConnection *r)
10787 {
10788         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10789         return WERR_NOT_SUPPORTED;
10790 }
10791
10792 /****************************************************************
10793  _spoolss_EnumPerMachineConnections
10794 ****************************************************************/
10795
10796 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10797                                           struct spoolss_EnumPerMachineConnections *r)
10798 {
10799         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10800         return WERR_NOT_SUPPORTED;
10801 }
10802
10803 /****************************************************************
10804  _spoolss_5a
10805 ****************************************************************/
10806
10807 WERROR _spoolss_5a(struct pipes_struct *p,
10808                    struct spoolss_5a *r)
10809 {
10810         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10811         return WERR_NOT_SUPPORTED;
10812 }
10813
10814 /****************************************************************
10815  _spoolss_5b
10816 ****************************************************************/
10817
10818 WERROR _spoolss_5b(struct pipes_struct *p,
10819                    struct spoolss_5b *r)
10820 {
10821         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10822         return WERR_NOT_SUPPORTED;
10823 }
10824
10825 /****************************************************************
10826  _spoolss_5c
10827 ****************************************************************/
10828
10829 WERROR _spoolss_5c(struct pipes_struct *p,
10830                    struct spoolss_5c *r)
10831 {
10832         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10833         return WERR_NOT_SUPPORTED;
10834 }
10835
10836 /****************************************************************
10837  _spoolss_5d
10838 ****************************************************************/
10839
10840 WERROR _spoolss_5d(struct pipes_struct *p,
10841                    struct spoolss_5d *r)
10842 {
10843         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10844         return WERR_NOT_SUPPORTED;
10845 }
10846
10847 /****************************************************************
10848  _spoolss_5e
10849 ****************************************************************/
10850
10851 WERROR _spoolss_5e(struct pipes_struct *p,
10852                    struct spoolss_5e *r)
10853 {
10854         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10855         return WERR_NOT_SUPPORTED;
10856 }
10857
10858 /****************************************************************
10859  _spoolss_5f
10860 ****************************************************************/
10861
10862 WERROR _spoolss_5f(struct pipes_struct *p,
10863                    struct spoolss_5f *r)
10864 {
10865         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10866         return WERR_NOT_SUPPORTED;
10867 }
10868
10869 /****************************************************************
10870  _spoolss_60
10871 ****************************************************************/
10872
10873 WERROR _spoolss_60(struct pipes_struct *p,
10874                    struct spoolss_60 *r)
10875 {
10876         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10877         return WERR_NOT_SUPPORTED;
10878 }
10879
10880 /****************************************************************
10881  _spoolss_RpcSendRecvBidiData
10882 ****************************************************************/
10883
10884 WERROR _spoolss_RpcSendRecvBidiData(struct pipes_struct *p,
10885                                     struct spoolss_RpcSendRecvBidiData *r)
10886 {
10887         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10888         return WERR_NOT_SUPPORTED;
10889 }
10890
10891 /****************************************************************
10892  _spoolss_62
10893 ****************************************************************/
10894
10895 WERROR _spoolss_62(struct pipes_struct *p,
10896                    struct spoolss_62 *r)
10897 {
10898         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10899         return WERR_NOT_SUPPORTED;
10900 }
10901
10902 /****************************************************************
10903  _spoolss_63
10904 ****************************************************************/
10905
10906 WERROR _spoolss_63(struct pipes_struct *p,
10907                    struct spoolss_63 *r)
10908 {
10909         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10910         return WERR_NOT_SUPPORTED;
10911 }
10912
10913 /****************************************************************
10914  _spoolss_64
10915 ****************************************************************/
10916
10917 WERROR _spoolss_64(struct pipes_struct *p,
10918                    struct spoolss_64 *r)
10919 {
10920         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10921         return WERR_NOT_SUPPORTED;
10922 }
10923
10924 /****************************************************************
10925  _spoolss_65
10926 ****************************************************************/
10927
10928 WERROR _spoolss_65(struct pipes_struct *p,
10929                    struct spoolss_65 *r)
10930 {
10931         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10932         return WERR_NOT_SUPPORTED;
10933 }
10934
10935 /****************************************************************
10936  _spoolss_GetCorePrinterDrivers
10937 ****************************************************************/
10938
10939 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10940                                       struct spoolss_GetCorePrinterDrivers *r)
10941 {
10942         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10943         return WERR_NOT_SUPPORTED;
10944 }
10945
10946 /****************************************************************
10947  _spoolss_67
10948 ****************************************************************/
10949
10950 WERROR _spoolss_67(struct pipes_struct *p,
10951                    struct spoolss_67 *r)
10952 {
10953         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10954         return WERR_NOT_SUPPORTED;
10955 }
10956
10957 /****************************************************************
10958  _spoolss_GetPrinterDriverPackagePath
10959 ****************************************************************/
10960
10961 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10962                                             struct spoolss_GetPrinterDriverPackagePath *r)
10963 {
10964         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10965         return WERR_NOT_SUPPORTED;
10966 }
10967
10968 /****************************************************************
10969  _spoolss_69
10970 ****************************************************************/
10971
10972 WERROR _spoolss_69(struct pipes_struct *p,
10973                    struct spoolss_69 *r)
10974 {
10975         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10976         return WERR_NOT_SUPPORTED;
10977 }
10978
10979 /****************************************************************
10980  _spoolss_6a
10981 ****************************************************************/
10982
10983 WERROR _spoolss_6a(struct pipes_struct *p,
10984                    struct spoolss_6a *r)
10985 {
10986         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10987         return WERR_NOT_SUPPORTED;
10988 }
10989
10990 /****************************************************************
10991  _spoolss_6b
10992 ****************************************************************/
10993
10994 WERROR _spoolss_6b(struct pipes_struct *p,
10995                    struct spoolss_6b *r)
10996 {
10997         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10998         return WERR_NOT_SUPPORTED;
10999 }
11000
11001 /****************************************************************
11002  _spoolss_6c
11003 ****************************************************************/
11004
11005 WERROR _spoolss_6c(struct pipes_struct *p,
11006                    struct spoolss_6c *r)
11007 {
11008         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11009         return WERR_NOT_SUPPORTED;
11010 }
11011
11012 /****************************************************************
11013  _spoolss_6d
11014 ****************************************************************/
11015
11016 WERROR _spoolss_6d(struct pipes_struct *p,
11017                    struct spoolss_6d *r)
11018 {
11019         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11020         return WERR_NOT_SUPPORTED;
11021 }
11022
11023 /****************************************************************
11024  _spoolss_RpcGetJobNamedPropertyValue
11025 ****************************************************************/
11026
11027 WERROR _spoolss_RpcGetJobNamedPropertyValue(struct pipes_struct *p,
11028                                             struct spoolss_RpcGetJobNamedPropertyValue *r)
11029 {
11030         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11031         return WERR_NOT_SUPPORTED;
11032 }
11033
11034 /****************************************************************
11035  _spoolss_RpcSetJobNamedProperty
11036 ****************************************************************/
11037
11038 WERROR _spoolss_RpcSetJobNamedProperty(struct pipes_struct *p,
11039                                        struct spoolss_RpcSetJobNamedProperty *r)
11040 {
11041         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11042         return WERR_NOT_SUPPORTED;
11043 }
11044
11045 /****************************************************************
11046  _spoolss_RpcDeleteJobNamedProperty
11047 ****************************************************************/
11048
11049 WERROR _spoolss_RpcDeleteJobNamedProperty(struct pipes_struct *p,
11050                                           struct spoolss_RpcDeleteJobNamedProperty *r)
11051 {
11052         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11053         return WERR_NOT_SUPPORTED;
11054 }
11055
11056 /****************************************************************
11057  _spoolss_RpcEnumJobNamedProperties
11058 ****************************************************************/
11059
11060 WERROR _spoolss_RpcEnumJobNamedProperties(struct pipes_struct *p,
11061                                           struct spoolss_RpcEnumJobNamedProperties *r)
11062 {
11063         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11064         return WERR_NOT_SUPPORTED;
11065 }