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