BUG 9574: Fix a possible null pointer dereference in spoolss.
[metze/samba/wip.git] / source3 / rpc_server / spoolss / srv_spoolss_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-2000,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6  *  Copyright (C) Jean François Micouleau      1998-2000,
7  *  Copyright (C) Jeremy Allison               2001-2002,
8  *  Copyright (C) Gerald Carter                2000-2004,
9  *  Copyright (C) Tim Potter                   2001-2002.
10  *  Copyright (C) Guenther Deschner            2009-2010.
11  *  Copyright (C) Andreas Schneider            2010.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 3 of the License, or
16  *  (at your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *  GNU General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License
24  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
25  */
26
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28    up, all the errors returned are DOS errors, not NT status codes. */
29
30 #include "includes.h"
31 #include "ntdomain.h"
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
40 #include "registry.h"
41 #include "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 != NULL &&
4470             (servername[0] == '\\') && (servername[1] == '\\')) {
4471                  s = servername + 2;
4472         }
4473
4474         if (is_myname_or_ipaddr(s)) {
4475                  return WERR_CAN_NOT_COMPLETE;
4476         }
4477
4478         return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4479                                         servername, PRINTER_ENUM_NAME, info, count);
4480 }
4481
4482 /********************************************************************
4483  * api_spoolss_enumprinters
4484  *
4485  * called from api_spoolss_enumprinters (see this to understand)
4486  ********************************************************************/
4487
4488 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4489                                        const struct auth_session_info *session_info,
4490                                        struct messaging_context *msg_ctx,
4491                                        const char *servername,
4492                                        union spoolss_PrinterInfo **info,
4493                                        uint32_t *count)
4494 {
4495         DEBUG(4,("enum_all_printers_info_2\n"));
4496
4497         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4498                                             servername, 2, 0, info, count);
4499 }
4500
4501 /********************************************************************
4502  * handle enumeration of printers at level 1
4503  ********************************************************************/
4504
4505 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4506                                   const struct auth_session_info *session_info,
4507                                   struct messaging_context *msg_ctx,
4508                                   uint32_t flags,
4509                                   const char *servername,
4510                                   union spoolss_PrinterInfo **info,
4511                                   uint32_t *count)
4512 {
4513         /* Not all the flags are equals */
4514
4515         if (flags & PRINTER_ENUM_LOCAL) {
4516                 return enum_all_printers_info_1_local(mem_ctx, session_info,
4517                                                       msg_ctx, servername, info, count);
4518         }
4519
4520         if (flags & PRINTER_ENUM_NAME) {
4521                 return enum_all_printers_info_1_name(mem_ctx, session_info,
4522                                                      msg_ctx, servername, info,
4523                                                      count);
4524         }
4525
4526         if (flags & PRINTER_ENUM_NETWORK) {
4527                 return enum_all_printers_info_1_network(mem_ctx, session_info,
4528                                                         msg_ctx, servername, info,
4529                                                         count);
4530         }
4531
4532         return WERR_OK; /* NT4sp5 does that */
4533 }
4534
4535 /********************************************************************
4536  * handle enumeration of printers at level 2
4537  ********************************************************************/
4538
4539 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4540                                   const struct auth_session_info *session_info,
4541                                   struct messaging_context *msg_ctx,
4542                                   uint32_t flags,
4543                                   const char *servername,
4544                                   union spoolss_PrinterInfo **info,
4545                                   uint32_t *count)
4546 {
4547         if (flags & PRINTER_ENUM_LOCAL) {
4548
4549                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4550                                                 servername,
4551                                                 info, count);
4552         }
4553
4554         if (flags & PRINTER_ENUM_NAME) {
4555                 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4556                         return WERR_INVALID_NAME;
4557                 }
4558
4559                 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4560                                                 servername,
4561                                                 info, count);
4562         }
4563
4564         if (flags & PRINTER_ENUM_REMOTE) {
4565                 return WERR_UNKNOWN_LEVEL;
4566         }
4567
4568         return WERR_OK;
4569 }
4570
4571 /********************************************************************
4572  * handle enumeration of printers at level 4
4573  ********************************************************************/
4574
4575 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4576                                   const struct auth_session_info *session_info,
4577                                   struct messaging_context *msg_ctx,
4578                                   uint32_t flags,
4579                                   const char *servername,
4580                                   union spoolss_PrinterInfo **info,
4581                                   uint32_t *count)
4582 {
4583         DEBUG(4,("enum_all_printers_info_4\n"));
4584
4585         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4586                                             servername, 4, flags, info, count);
4587 }
4588
4589
4590 /********************************************************************
4591  * handle enumeration of printers at level 5
4592  ********************************************************************/
4593
4594 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4595                                   const struct auth_session_info *session_info,
4596                                   struct messaging_context *msg_ctx,
4597                                   uint32_t flags,
4598                                   const char *servername,
4599                                   union spoolss_PrinterInfo **info,
4600                                   uint32_t *count)
4601 {
4602         DEBUG(4,("enum_all_printers_info_5\n"));
4603
4604         return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4605                                             servername, 5, flags, info, count);
4606 }
4607
4608 /****************************************************************
4609  _spoolss_EnumPrinters
4610 ****************************************************************/
4611
4612 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4613                              struct spoolss_EnumPrinters *r)
4614 {
4615         const struct auth_session_info *session_info = get_session_info_system();
4616         WERROR result;
4617
4618         /* that's an [in out] buffer */
4619
4620         if (!r->in.buffer && (r->in.offered != 0)) {
4621                 return WERR_INVALID_PARAM;
4622         }
4623
4624         DEBUG(4,("_spoolss_EnumPrinters\n"));
4625
4626         *r->out.needed = 0;
4627         *r->out.count = 0;
4628         *r->out.info = NULL;
4629
4630         /*
4631          * Level 1:
4632          *          flags==PRINTER_ENUM_NAME
4633          *           if name=="" then enumerates all printers
4634          *           if name!="" then enumerate the printer
4635          *          flags==PRINTER_ENUM_REMOTE
4636          *          name is NULL, enumerate printers
4637          * Level 2: name!="" enumerates printers, name can't be NULL
4638          * Level 3: doesn't exist
4639          * Level 4: does a local registry lookup
4640          * Level 5: same as Level 2
4641          */
4642
4643         if (r->in.server && r->in.server[0] == '\0') {
4644                 r->in.server = NULL;
4645         }
4646
4647         switch (r->in.level) {
4648         case 0:
4649                 result = enumprinters_level0(p->mem_ctx, session_info,
4650                                              p->msg_ctx, r->in.flags,
4651                                              r->in.server,
4652                                              r->out.info, r->out.count);
4653                 break;
4654         case 1:
4655                 result = enumprinters_level1(p->mem_ctx, session_info,
4656                                              p->msg_ctx, r->in.flags,
4657                                              r->in.server,
4658                                              r->out.info, r->out.count);
4659                 break;
4660         case 2:
4661                 result = enumprinters_level2(p->mem_ctx, session_info,
4662                                              p->msg_ctx, r->in.flags,
4663                                              r->in.server,
4664                                              r->out.info, r->out.count);
4665                 break;
4666         case 4:
4667                 result = enumprinters_level4(p->mem_ctx, session_info,
4668                                              p->msg_ctx, r->in.flags,
4669                                              r->in.server,
4670                                              r->out.info, r->out.count);
4671                 break;
4672         case 5:
4673                 result = enumprinters_level5(p->mem_ctx, session_info,
4674                                              p->msg_ctx, r->in.flags,
4675                                              r->in.server,
4676                                              r->out.info, r->out.count);
4677                 break;
4678         default:
4679                 return WERR_UNKNOWN_LEVEL;
4680         }
4681
4682         if (!W_ERROR_IS_OK(result)) {
4683                 return result;
4684         }
4685
4686         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4687                                                      spoolss_EnumPrinters,
4688                                                      *r->out.info, r->in.level,
4689                                                      *r->out.count);
4690         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4691         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4692
4693         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4694 }
4695
4696 /****************************************************************
4697  _spoolss_GetPrinter
4698 ****************************************************************/
4699
4700 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4701                            struct spoolss_GetPrinter *r)
4702 {
4703         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4704         struct spoolss_PrinterInfo2 *info2 = NULL;
4705         WERROR result = WERR_OK;
4706         int snum;
4707
4708         /* that's an [in out] buffer */
4709
4710         if (!r->in.buffer && (r->in.offered != 0)) {
4711                 return WERR_INVALID_PARAM;
4712         }
4713
4714         *r->out.needed = 0;
4715
4716         if (Printer == NULL) {
4717                 return WERR_BADFID;
4718         }
4719
4720         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4721                 return WERR_BADFID;
4722         }
4723
4724         result = winreg_get_printer_internal(p->mem_ctx,
4725                                     get_session_info_system(),
4726                                     p->msg_ctx,
4727                                     lp_const_servicename(snum),
4728                                     &info2);
4729         if (!W_ERROR_IS_OK(result)) {
4730                 goto out;
4731         }
4732
4733         switch (r->in.level) {
4734         case 0:
4735                 result = construct_printer_info0(p->mem_ctx,
4736                                                  get_session_info_system(),
4737                                                  p->msg_ctx,
4738                                                  info2,
4739                                                  Printer->servername,
4740                                                  &r->out.info->info0,
4741                                                  snum);
4742                 break;
4743         case 1:
4744                 result = construct_printer_info1(p->mem_ctx, info2,
4745                                                  PRINTER_ENUM_ICON8,
4746                                                  Printer->servername,
4747                                                  &r->out.info->info1, snum);
4748                 break;
4749         case 2:
4750                 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4751                                                  Printer->servername,
4752                                                  &r->out.info->info2, snum);
4753                 break;
4754         case 3:
4755                 result = construct_printer_info3(p->mem_ctx, info2,
4756                                                  Printer->servername,
4757                                                  &r->out.info->info3, snum);
4758                 break;
4759         case 4:
4760                 result = construct_printer_info4(p->mem_ctx, info2,
4761                                                  Printer->servername,
4762                                                  &r->out.info->info4, snum);
4763                 break;
4764         case 5:
4765                 result = construct_printer_info5(p->mem_ctx, info2,
4766                                                  Printer->servername,
4767                                                  &r->out.info->info5, snum);
4768                 break;
4769         case 6:
4770                 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4771                                                  Printer->servername,
4772                                                  &r->out.info->info6, snum);
4773                 break;
4774         case 7:
4775                 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4776                                                  Printer->servername,
4777                                                  &r->out.info->info7, snum);
4778                 break;
4779         case 8:
4780                 result = construct_printer_info8(p->mem_ctx, info2,
4781                                                  Printer->servername,
4782                                                  &r->out.info->info8, snum);
4783                 break;
4784         default:
4785                 result = WERR_UNKNOWN_LEVEL;
4786                 break;
4787         }
4788         TALLOC_FREE(info2);
4789
4790  out:
4791         if (!W_ERROR_IS_OK(result)) {
4792                 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4793                           r->in.level, win_errstr(result)));
4794                 TALLOC_FREE(r->out.info);
4795                 return result;
4796         }
4797
4798         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4799                                                r->out.info, r->in.level);
4800         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4801
4802         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4803 }
4804
4805 /********************************************************************
4806  ********************************************************************/
4807
4808 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4809         do { \
4810                 if (in && strlen(in)) { \
4811                         out = talloc_strdup(mem_ctx, in); \
4812                 } else { \
4813                         out = talloc_strdup(mem_ctx, ""); \
4814                 } \
4815                 W_ERROR_HAVE_NO_MEMORY(out); \
4816         } while (0);
4817
4818 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4819         do { \
4820                 if (in && strlen(in)) { \
4821                         out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4822                 } else { \
4823                         out = talloc_strdup(mem_ctx, ""); \
4824                 } \
4825                 W_ERROR_HAVE_NO_MEMORY(out); \
4826         } while (0);
4827
4828 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4829                                                   const char **string_array,
4830                                                   const char ***presult,
4831                                                   const char *cservername,
4832                                                   const char *arch,
4833                                                   int version)
4834 {
4835         int i, num_strings = 0;
4836         const char **array = NULL;
4837
4838         if (string_array == NULL) {
4839                 return WERR_INVALID_PARAMETER;
4840         }
4841
4842         for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4843                 const char *str = NULL;
4844
4845                 if (cservername == NULL || arch == NULL) {
4846                         FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4847                 } else {
4848                         FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4849                 }
4850
4851                 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4852                         TALLOC_FREE(array);
4853                         return WERR_NOMEM;
4854                 }
4855         }
4856
4857         if (i > 0) {
4858                 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4859                              &array, &num_strings);
4860         }
4861
4862         if (presult) {
4863                 *presult = array;
4864         }
4865
4866         return WERR_OK;
4867 }
4868
4869 /********************************************************************
4870  * fill a spoolss_DriverInfo1 struct
4871  ********************************************************************/
4872
4873 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4874                                         struct spoolss_DriverInfo1 *r,
4875                                         const struct spoolss_DriverInfo8 *driver,
4876                                         const char *servername)
4877 {
4878         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4879         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4880
4881         return WERR_OK;
4882 }
4883
4884 /********************************************************************
4885  * fill a spoolss_DriverInfo2 struct
4886  ********************************************************************/
4887
4888 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4889                                         struct spoolss_DriverInfo2 *r,
4890                                         const struct spoolss_DriverInfo8 *driver,
4891                                         const char *servername)
4892
4893 {
4894         const char *cservername = canon_servername(servername);
4895
4896         r->version              = driver->version;
4897
4898         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4899         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4900         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4901         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4902
4903         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4904                                driver->architecture,
4905                                driver->version,
4906                                driver->driver_path,
4907                                r->driver_path);
4908
4909         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4910                                driver->architecture,
4911                                driver->version,
4912                                driver->data_file,
4913                                r->data_file);
4914
4915         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4916                                driver->architecture,
4917                                driver->version,
4918                                driver->config_file,
4919                                r->config_file);
4920
4921         return WERR_OK;
4922 }
4923
4924 /********************************************************************
4925  * fill a spoolss_DriverInfo3 struct
4926  ********************************************************************/
4927
4928 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4929                                         struct spoolss_DriverInfo3 *r,
4930                                         const struct spoolss_DriverInfo8 *driver,
4931                                         const char *servername)
4932 {
4933         const char *cservername = canon_servername(servername);
4934
4935         r->version              = driver->version;
4936
4937         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4938         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4939         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4940         W_ERROR_HAVE_NO_MEMORY(r->architecture);
4941
4942         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4943                                driver->architecture,
4944                                driver->version,
4945                                driver->driver_path,
4946                                r->driver_path);
4947
4948         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4949                                driver->architecture,
4950                                driver->version,
4951                                driver->data_file,
4952                                r->data_file);
4953
4954         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4955                                driver->architecture,
4956                                driver->version,
4957                                driver->config_file,
4958                                r->config_file);
4959
4960         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4961                                driver->architecture,
4962                                driver->version,
4963                                driver->help_file,
4964                                r->help_file);
4965
4966         FILL_DRIVER_STRING(mem_ctx,
4967                            driver->monitor_name,
4968                            r->monitor_name);
4969
4970         FILL_DRIVER_STRING(mem_ctx,
4971                            driver->default_datatype,
4972                            r->default_datatype);
4973
4974         return string_array_from_driver_info(mem_ctx,
4975                                              driver->dependent_files,
4976                                              &r->dependent_files,
4977                                              cservername,
4978                                              driver->architecture,
4979                                              driver->version);
4980 }
4981
4982 /********************************************************************
4983  * fill a spoolss_DriverInfo4 struct
4984  ********************************************************************/
4985
4986 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4987                                         struct spoolss_DriverInfo4 *r,
4988                                         const struct spoolss_DriverInfo8 *driver,
4989                                         const char *servername)
4990 {
4991         const char *cservername = canon_servername(servername);
4992         WERROR result;
4993
4994         r->version              = driver->version;
4995
4996         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
4997         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4998         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
4999         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5000
5001         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5002                                driver->architecture,
5003                                driver->version,
5004                                driver->driver_path,
5005                                r->driver_path);
5006
5007         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5008                                driver->architecture,
5009                                driver->version,
5010                                driver->data_file,
5011                                r->data_file);
5012
5013         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5014                                driver->architecture,
5015                                driver->version,
5016                                driver->config_file,
5017                                r->config_file);
5018
5019         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5020                                driver->architecture,
5021                                driver->version,
5022                                driver->help_file,
5023                                r->help_file);
5024
5025         result = string_array_from_driver_info(mem_ctx,
5026                                                driver->dependent_files,
5027                                                &r->dependent_files,
5028                                                cservername,
5029                                                driver->architecture,
5030                                                driver->version);
5031         if (!W_ERROR_IS_OK(result)) {
5032                 return result;
5033         }
5034
5035         FILL_DRIVER_STRING(mem_ctx,
5036                            driver->monitor_name,
5037                            r->monitor_name);
5038
5039         FILL_DRIVER_STRING(mem_ctx,
5040                            driver->default_datatype,
5041                            r->default_datatype);
5042
5043
5044         result = string_array_from_driver_info(mem_ctx,
5045                                                driver->previous_names,
5046                                                &r->previous_names,
5047                                                NULL, NULL, 0);
5048
5049         return result;
5050 }
5051
5052 /********************************************************************
5053  * fill a spoolss_DriverInfo5 struct
5054  ********************************************************************/
5055
5056 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5057                                         struct spoolss_DriverInfo5 *r,
5058                                         const struct spoolss_DriverInfo8 *driver,
5059                                         const char *servername)
5060 {
5061         const char *cservername = canon_servername(servername);
5062
5063         r->version              = driver->version;
5064
5065         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5066         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5067         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5068         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5069
5070         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5071                                driver->architecture,
5072                                driver->version,
5073                                driver->driver_path,
5074                                r->driver_path);
5075
5076         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5077                                driver->architecture,
5078                                driver->version,
5079                                driver->data_file,
5080                                r->data_file);
5081
5082         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5083                                driver->architecture,
5084                                driver->version,
5085                                driver->config_file,
5086                                r->config_file);
5087
5088         r->driver_attributes    = 0;
5089         r->config_version       = 0;
5090         r->driver_version       = 0;
5091
5092         return WERR_OK;
5093 }
5094 /********************************************************************
5095  * fill a spoolss_DriverInfo6 struct
5096  ********************************************************************/
5097
5098 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5099                                         struct spoolss_DriverInfo6 *r,
5100                                         const struct spoolss_DriverInfo8 *driver,
5101                                         const char *servername)
5102 {
5103         const char *cservername = canon_servername(servername);
5104         WERROR result;
5105
5106         r->version              = driver->version;
5107
5108         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5109         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5110         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5111         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5112
5113         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5114                                driver->architecture,
5115                                driver->version,
5116                                driver->driver_path,
5117                                r->driver_path);
5118
5119         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5120                                driver->architecture,
5121                                driver->version,
5122                                driver->data_file,
5123                                r->data_file);
5124
5125         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5126                                driver->architecture,
5127                                driver->version,
5128                                driver->config_file,
5129                                r->config_file);
5130
5131         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5132                                driver->architecture,
5133                                driver->version,
5134                                driver->help_file,
5135                                r->help_file);
5136
5137         FILL_DRIVER_STRING(mem_ctx,
5138                            driver->monitor_name,
5139                            r->monitor_name);
5140
5141         FILL_DRIVER_STRING(mem_ctx,
5142                            driver->default_datatype,
5143                            r->default_datatype);
5144
5145         result = string_array_from_driver_info(mem_ctx,
5146                                                driver->dependent_files,
5147                                                &r->dependent_files,
5148                                                cservername,
5149                                                driver->architecture,
5150                                                driver->version);
5151         if (!W_ERROR_IS_OK(result)) {
5152                 return result;
5153         }
5154
5155         result = string_array_from_driver_info(mem_ctx,
5156                                                driver->previous_names,
5157                                                &r->previous_names,
5158                                                NULL, NULL, 0);
5159         if (!W_ERROR_IS_OK(result)) {
5160                 return result;
5161         }
5162
5163         r->driver_date          = driver->driver_date;
5164         r->driver_version       = driver->driver_version;
5165
5166         FILL_DRIVER_STRING(mem_ctx,
5167                            driver->manufacturer_name,
5168                            r->manufacturer_name);
5169         FILL_DRIVER_STRING(mem_ctx,
5170                            driver->manufacturer_url,
5171                            r->manufacturer_url);
5172         FILL_DRIVER_STRING(mem_ctx,
5173                            driver->hardware_id,
5174                            r->hardware_id);
5175         FILL_DRIVER_STRING(mem_ctx,
5176                            driver->provider,
5177                            r->provider);
5178
5179         return WERR_OK;
5180 }
5181
5182 /********************************************************************
5183  * fill a spoolss_DriverInfo8 struct
5184  ********************************************************************/
5185
5186 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5187                                         struct spoolss_DriverInfo8 *r,
5188                                         const struct spoolss_DriverInfo8 *driver,
5189                                         const char *servername)
5190 {
5191         const char *cservername = canon_servername(servername);
5192         WERROR result;
5193
5194         r->version              = driver->version;
5195
5196         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5197         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5198         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5199         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5200
5201         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5202                                driver->architecture,
5203                                driver->version,
5204                                driver->driver_path,
5205                                r->driver_path);
5206
5207         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5208                                driver->architecture,
5209                                driver->version,
5210                                driver->data_file,
5211                                r->data_file);
5212
5213         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5214                                driver->architecture,
5215                                driver->version,
5216                                driver->config_file,
5217                                r->config_file);
5218
5219         FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5220                                driver->architecture,
5221                                driver->version,
5222                                driver->help_file,
5223                                r->help_file);
5224
5225         FILL_DRIVER_STRING(mem_ctx,
5226                            driver->monitor_name,
5227                            r->monitor_name);
5228
5229         FILL_DRIVER_STRING(mem_ctx,
5230                            driver->default_datatype,
5231                            r->default_datatype);
5232
5233         result = string_array_from_driver_info(mem_ctx,
5234                                                driver->dependent_files,
5235                                                &r->dependent_files,
5236                                                cservername,
5237                                                driver->architecture,
5238                                                driver->version);
5239         if (!W_ERROR_IS_OK(result)) {
5240                 return result;
5241         }
5242
5243         result = string_array_from_driver_info(mem_ctx,
5244                                                driver->previous_names,
5245                                                &r->previous_names,
5246                                                NULL, NULL, 0);
5247         if (!W_ERROR_IS_OK(result)) {
5248                 return result;
5249         }
5250
5251         r->driver_date          = driver->driver_date;
5252         r->driver_version       = driver->driver_version;
5253
5254         FILL_DRIVER_STRING(mem_ctx,
5255                            driver->manufacturer_name,
5256                            r->manufacturer_name);
5257         FILL_DRIVER_STRING(mem_ctx,
5258                            driver->manufacturer_url,
5259                            r->manufacturer_url);
5260         FILL_DRIVER_STRING(mem_ctx,
5261                            driver->hardware_id,
5262                            r->hardware_id);
5263         FILL_DRIVER_STRING(mem_ctx,
5264                            driver->provider,
5265                            r->provider);
5266
5267         FILL_DRIVER_STRING(mem_ctx,
5268                            driver->print_processor,
5269                            r->print_processor);
5270         FILL_DRIVER_STRING(mem_ctx,
5271                            driver->vendor_setup,
5272                            r->vendor_setup);
5273
5274         result = string_array_from_driver_info(mem_ctx,
5275                                                driver->color_profiles,
5276                                                &r->color_profiles,
5277                                                NULL, NULL, 0);
5278         if (!W_ERROR_IS_OK(result)) {
5279                 return result;
5280         }
5281
5282         FILL_DRIVER_STRING(mem_ctx,
5283                            driver->inf_path,
5284                            r->inf_path);
5285
5286         r->printer_driver_attributes    = driver->printer_driver_attributes;
5287
5288         result = string_array_from_driver_info(mem_ctx,
5289                                                driver->core_driver_dependencies,
5290                                                &r->core_driver_dependencies,
5291                                                NULL, NULL, 0);
5292         if (!W_ERROR_IS_OK(result)) {
5293                 return result;
5294         }
5295
5296         r->min_inbox_driver_ver_date    = driver->min_inbox_driver_ver_date;
5297         r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5298
5299         return WERR_OK;
5300 }
5301
5302 #if 0 /* disabled until marshalling issues are resolved - gd */
5303 /********************************************************************
5304  ********************************************************************/
5305
5306 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5307                                           struct spoolss_DriverFileInfo *r,
5308                                           const char *cservername,
5309                                           const char *file_name,
5310                                           enum spoolss_DriverFileType file_type,
5311                                           uint32_t file_version)
5312 {
5313         r->file_name    = talloc_asprintf(mem_ctx, "\\\\%s%s",
5314                                           cservername, file_name);
5315         W_ERROR_HAVE_NO_MEMORY(r->file_name);
5316         r->file_type    = file_type;
5317         r->file_version = file_version;
5318
5319         return WERR_OK;
5320 }
5321
5322 /********************************************************************
5323  ********************************************************************/
5324
5325 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5326                                                  const struct spoolss_DriverInfo8 *driver,
5327                                                  const char *cservername,
5328                                                  struct spoolss_DriverFileInfo **info_p,
5329                                                  uint32_t *count_p)
5330 {
5331         struct spoolss_DriverFileInfo *info = NULL;
5332         uint32_t count = 0;
5333         WERROR result;
5334         uint32_t i;
5335
5336         *info_p = NULL;
5337         *count_p = 0;
5338
5339         if (strlen(driver->driver_path)) {
5340                 info = talloc_realloc(mem_ctx, info,
5341                                             struct spoolss_DriverFileInfo,
5342                                             count + 1);
5343                 W_ERROR_HAVE_NO_MEMORY(info);
5344                 result = fill_spoolss_DriverFileInfo(info,
5345                                                      &info[count],
5346                                                      cservername,
5347                                                      driver->driver_path,
5348                                                      SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5349                                                      0);
5350                 W_ERROR_NOT_OK_RETURN(result);
5351                 count++;
5352         }
5353
5354         if (strlen(driver->config_file)) {
5355                 info = talloc_realloc(mem_ctx, info,
5356                                             struct spoolss_DriverFileInfo,
5357                                             count + 1);
5358                 W_ERROR_HAVE_NO_MEMORY(info);
5359                 result = fill_spoolss_DriverFileInfo(info,
5360                                                      &info[count],
5361                                                      cservername,
5362                                                      driver->config_file,
5363                                                      SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5364                                                      0);
5365                 W_ERROR_NOT_OK_RETURN(result);
5366                 count++;
5367         }
5368
5369         if (strlen(driver->data_file)) {
5370                 info = talloc_realloc(mem_ctx, info,
5371                                             struct spoolss_DriverFileInfo,
5372                                             count + 1);
5373                 W_ERROR_HAVE_NO_MEMORY(info);
5374                 result = fill_spoolss_DriverFileInfo(info,
5375                                                      &info[count],
5376                                                      cservername,
5377                                                      driver->data_file,
5378                                                      SPOOLSS_DRIVER_FILE_TYPE_DATA,
5379                                                      0);
5380                 W_ERROR_NOT_OK_RETURN(result);
5381                 count++;
5382         }
5383
5384         if (strlen(driver->help_file)) {
5385                 info = talloc_realloc(mem_ctx, info,
5386                                             struct spoolss_DriverFileInfo,
5387                                             count + 1);
5388                 W_ERROR_HAVE_NO_MEMORY(info);
5389                 result = fill_spoolss_DriverFileInfo(info,
5390                                                      &info[count],
5391                                                      cservername,
5392                                                      driver->help_file,
5393                                                      SPOOLSS_DRIVER_FILE_TYPE_HELP,
5394                                                      0);
5395                 W_ERROR_NOT_OK_RETURN(result);
5396                 count++;
5397         }
5398
5399         for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5400                 info = talloc_realloc(mem_ctx, info,
5401                                             struct spoolss_DriverFileInfo,
5402                                             count + 1);
5403                 W_ERROR_HAVE_NO_MEMORY(info);
5404                 result = fill_spoolss_DriverFileInfo(info,
5405                                                      &info[count],
5406                                                      cservername,
5407                                                      driver->dependent_files[i],
5408                                                      SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5409                                                      0);
5410                 W_ERROR_NOT_OK_RETURN(result);
5411                 count++;
5412         }
5413
5414         *info_p = info;
5415         *count_p = count;
5416
5417         return WERR_OK;
5418 }
5419
5420 /********************************************************************
5421  * fill a spoolss_DriverInfo101 struct
5422  ********************************************************************/
5423
5424 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5425                                           struct spoolss_DriverInfo101 *r,
5426                                           const struct spoolss_DriverInfo8 *driver,
5427                                           const char *servername)
5428 {
5429         const char *cservername = canon_servername(servername);
5430         WERROR result;
5431
5432         r->version              = driver->version;
5433
5434         r->driver_name          = talloc_strdup(mem_ctx, driver->driver_name);
5435         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5436         r->architecture         = talloc_strdup(mem_ctx, driver->architecture);
5437         W_ERROR_HAVE_NO_MEMORY(r->architecture);
5438
5439         result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5440                                                     cservername,
5441                                                     &r->file_info,
5442                                                     &r->file_count);
5443         if (!W_ERROR_IS_OK(result)) {
5444                 return result;
5445         }
5446
5447         FILL_DRIVER_STRING(mem_ctx,
5448                            driver->monitor_name,
5449                            r->monitor_name);
5450
5451         FILL_DRIVER_STRING(mem_ctx,
5452                            driver->default_datatype,
5453                            r->default_datatype);
5454
5455         result = string_array_from_driver_info(mem_ctx,
5456                                                driver->previous_names,
5457                                                &r->previous_names,
5458                                                NULL, NULL, 0);
5459         if (!W_ERROR_IS_OK(result)) {
5460                 return result;
5461         }
5462
5463         r->driver_date          = driver->driver_date;
5464         r->driver_version       = driver->driver_version;
5465
5466         FILL_DRIVER_STRING(mem_ctx,
5467                            driver->manufacturer_name,
5468                            r->manufacturer_name);
5469         FILL_DRIVER_STRING(mem_ctx,
5470                            driver->manufacturer_url,
5471                            r->manufacturer_url);
5472         FILL_DRIVER_STRING(mem_ctx,
5473                            driver->hardware_id,
5474                            r->hardware_id);
5475         FILL_DRIVER_STRING(mem_ctx,
5476                            driver->provider,
5477                            r->provider);
5478
5479         return WERR_OK;
5480 }
5481 #endif
5482 /********************************************************************
5483  ********************************************************************/
5484
5485 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5486                                                   const struct auth_session_info *session_info,
5487                                                   struct messaging_context *msg_ctx,
5488                                                   uint32_t level,
5489                                                   union spoolss_DriverInfo *r,
5490                                                   int snum,
5491                                                   const char *servername,
5492                                                   const char *architecture,
5493                                                   uint32_t version)
5494 {
5495         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5496         struct spoolss_DriverInfo8 *driver;
5497         WERROR result;
5498         struct dcerpc_binding_handle *b;
5499         TALLOC_CTX *tmp_ctx = NULL;
5500
5501         if (level == 101) {
5502                 return WERR_UNKNOWN_LEVEL;
5503         }
5504
5505         tmp_ctx = talloc_new(mem_ctx);
5506         if (!tmp_ctx) {
5507                 return WERR_NOMEM;
5508         }
5509
5510         result = winreg_printer_binding_handle(tmp_ctx,
5511                                                session_info,
5512                                                msg_ctx,
5513                                                &b);
5514         if (!W_ERROR_IS_OK(result)) {
5515                 goto done;
5516         }
5517
5518         result = winreg_get_printer(tmp_ctx, b,
5519                                     lp_const_servicename(snum),
5520                                     &pinfo2);
5521
5522         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5523                 win_errstr(result)));
5524
5525         if (!W_ERROR_IS_OK(result)) {
5526                 result = WERR_INVALID_PRINTER_NAME;
5527                 goto done;
5528         }
5529
5530         result = winreg_get_driver(tmp_ctx, b,
5531                                    architecture,
5532                                    pinfo2->drivername, version, &driver);
5533
5534         DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5535                 win_errstr(result)));
5536
5537         if (!W_ERROR_IS_OK(result)) {
5538                 /*
5539                  * Is this a W2k client ?
5540                  */
5541
5542                 if (version < 3) {
5543                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5544                         goto done;
5545                 }
5546
5547                 /* Yes - try again with a WinNT driver. */
5548                 version = 2;
5549                 result = winreg_get_driver(tmp_ctx, b,
5550                                            architecture,
5551                                            pinfo2->drivername,
5552                                            version, &driver);
5553                 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5554                         win_errstr(result)));
5555                 if (!W_ERROR_IS_OK(result)) {
5556                         result = WERR_UNKNOWN_PRINTER_DRIVER;
5557                         goto done;
5558                 }
5559         }
5560
5561         /* these are allocated on mem_ctx and not tmp_ctx because they are
5562          * the 'return value' and need to utlive this call */
5563         switch (level) {
5564         case 1:
5565                 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5566                 break;
5567         case 2:
5568                 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5569                 break;
5570         case 3:
5571                 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5572                 break;
5573         case 4:
5574                 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5575                 break;
5576         case 5:
5577                 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5578                 break;
5579         case 6:
5580                 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5581                 break;
5582         case 8:
5583                 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5584                 break;
5585 #if 0 /* disabled until marshalling issues are resolved - gd */
5586         case 101:
5587                 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5588                 break;
5589 #endif
5590         default:
5591                 result = WERR_UNKNOWN_LEVEL;
5592                 break;
5593         }
5594
5595 done:
5596         talloc_free(tmp_ctx);
5597         return result;
5598 }
5599
5600 /****************************************************************
5601  _spoolss_GetPrinterDriver2
5602 ****************************************************************/
5603
5604 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5605                                   struct spoolss_GetPrinterDriver2 *r)
5606 {
5607         struct printer_handle *printer;
5608         WERROR result;
5609
5610         int snum;
5611
5612         /* that's an [in out] buffer */
5613
5614         if (!r->in.buffer && (r->in.offered != 0)) {
5615                 return WERR_INVALID_PARAM;
5616         }
5617
5618         DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5619
5620         if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5621                 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5622                 return WERR_INVALID_PRINTER_NAME;
5623         }
5624
5625         *r->out.needed = 0;
5626         *r->out.server_major_version = 0;
5627         *r->out.server_minor_version = 0;
5628
5629         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5630                 return WERR_BADFID;
5631         }
5632
5633         result = construct_printer_driver_info_level(p->mem_ctx,
5634                                                      get_session_info_system(),
5635                                                      p->msg_ctx,
5636                                                      r->in.level, r->out.info,
5637                                                      snum, printer->servername,
5638                                                      r->in.architecture,
5639                                                      r->in.client_major_version);
5640         if (!W_ERROR_IS_OK(result)) {
5641                 TALLOC_FREE(r->out.info);
5642                 return result;
5643         }
5644
5645         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5646                                                r->out.info, r->in.level);
5647         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5648
5649         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5650 }
5651
5652
5653 /****************************************************************
5654  _spoolss_StartPagePrinter
5655 ****************************************************************/
5656
5657 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5658                                  struct spoolss_StartPagePrinter *r)
5659 {
5660         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5661
5662         if (!Printer) {
5663                 DEBUG(3,("_spoolss_StartPagePrinter: "
5664                         "Error in startpageprinter printer handle\n"));
5665                 return WERR_BADFID;
5666         }
5667
5668         Printer->page_started = true;
5669         return WERR_OK;
5670 }
5671
5672 /****************************************************************
5673  _spoolss_EndPagePrinter
5674 ****************************************************************/
5675
5676 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5677                                struct spoolss_EndPagePrinter *r)
5678 {
5679         int snum;
5680
5681         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5682
5683         if (!Printer) {
5684                 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5685                         OUR_HANDLE(r->in.handle)));
5686                 return WERR_BADFID;
5687         }
5688
5689         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5690                 return WERR_BADFID;
5691
5692         Printer->page_started = false;
5693         print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5694
5695         return WERR_OK;
5696 }
5697
5698 /****************************************************************
5699  _spoolss_StartDocPrinter
5700 ****************************************************************/
5701
5702 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5703                                 struct spoolss_StartDocPrinter *r)
5704 {
5705         struct spoolss_DocumentInfo1 *info_1;
5706         int snum;
5707         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5708         WERROR werr;
5709         char *rhost;
5710         int rc;
5711
5712         if (!Printer) {
5713                 DEBUG(2,("_spoolss_StartDocPrinter: "
5714                         "Invalid handle (%s:%u:%u)\n",
5715                         OUR_HANDLE(r->in.handle)));
5716                 return WERR_BADFID;
5717         }
5718
5719         if (Printer->jobid) {
5720                 DEBUG(2, ("_spoolss_StartDocPrinter: "
5721                           "StartDocPrinter called twice! "
5722                           "(existing jobid = %d)\n", Printer->jobid));
5723                 return WERR_INVALID_HANDLE;
5724         }
5725
5726         if (r->in.level != 1) {
5727                 return WERR_UNKNOWN_LEVEL;
5728         }
5729
5730         info_1 = r->in.info.info1;
5731
5732         /*
5733          * a nice thing with NT is it doesn't listen to what you tell it.
5734          * when asked to send _only_ RAW datas, it tries to send datas
5735          * in EMF format.
5736          *
5737          * So I add checks like in NT Server ...
5738          */
5739
5740         if (info_1->datatype) {
5741                 if (strcmp(info_1->datatype, "RAW") != 0) {
5742                         *r->out.job_id = 0;
5743                         return WERR_INVALID_DATATYPE;
5744                 }
5745         }
5746
5747         /* get the share number of the printer */
5748         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5749                 return WERR_BADFID;
5750         }
5751
5752         rc = get_remote_hostname(p->remote_address,
5753                                  &rhost,
5754                                  p->mem_ctx);
5755         if (rc < 0) {
5756                 return WERR_NOMEM;
5757         }
5758         if (strequal(rhost,"UNKNOWN")) {
5759                 rhost = tsocket_address_inet_addr_string(p->remote_address,
5760                                                          p->mem_ctx);
5761                 if (rhost == NULL) {
5762                         return WERR_NOMEM;
5763                 }
5764         }
5765
5766         werr = print_job_start(p->session_info,
5767                                p->msg_ctx,
5768                                rhost,
5769                                snum,
5770                                info_1->document_name,
5771                                info_1->output_file,
5772                                Printer->devmode,
5773                                &Printer->jobid);
5774
5775         /* An error occured in print_job_start() so return an appropriate
5776            NT error code. */
5777
5778         if (!W_ERROR_IS_OK(werr)) {
5779                 return werr;
5780         }
5781
5782         Printer->document_started = true;
5783         *r->out.job_id = Printer->jobid;
5784
5785         return WERR_OK;
5786 }
5787
5788 /****************************************************************
5789  _spoolss_EndDocPrinter
5790 ****************************************************************/
5791
5792 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5793                               struct spoolss_EndDocPrinter *r)
5794 {
5795         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5796         NTSTATUS status;
5797         int snum;
5798
5799         if (!Printer) {
5800                 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5801                         OUR_HANDLE(r->in.handle)));
5802                 return WERR_BADFID;
5803         }
5804
5805         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5806                 return WERR_BADFID;
5807         }
5808
5809         Printer->document_started = false;
5810         status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5811         if (!NT_STATUS_IS_OK(status)) {
5812                 DEBUG(2, ("_spoolss_EndDocPrinter: "
5813                           "print_job_end failed [%s]\n",
5814                           nt_errstr(status)));
5815         }
5816
5817         Printer->jobid = 0;
5818         return ntstatus_to_werror(status);
5819 }
5820
5821 /****************************************************************
5822  _spoolss_WritePrinter
5823 ****************************************************************/
5824
5825 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5826                              struct spoolss_WritePrinter *r)
5827 {
5828         ssize_t buffer_written;
5829         int snum;
5830         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5831
5832         if (!Printer) {
5833                 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5834                         OUR_HANDLE(r->in.handle)));
5835                 *r->out.num_written = r->in._data_size;
5836                 return WERR_BADFID;
5837         }
5838
5839         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5840                 return WERR_BADFID;
5841
5842         /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5843         buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5844                                                    snum, Printer->jobid,
5845                                                    (const char *)r->in.data.data,
5846                                                    (size_t)r->in._data_size);
5847         if (buffer_written == (ssize_t)-1) {
5848                 *r->out.num_written = 0;
5849                 if (errno == ENOSPC)
5850                         return WERR_NO_SPOOL_SPACE;
5851                 else
5852                         return WERR_ACCESS_DENIED;
5853         }
5854
5855         *r->out.num_written = r->in._data_size;
5856
5857         return WERR_OK;
5858 }
5859
5860 /********************************************************************
5861  * api_spoolss_getprinter
5862  * called from the spoolss dispatcher
5863  *
5864  ********************************************************************/
5865
5866 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5867                               struct pipes_struct *p)
5868 {
5869         const struct auth_session_info *session_info = p->session_info;
5870         int snum;
5871         WERROR errcode = WERR_BADFUNC;
5872         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5873
5874         if (!Printer) {
5875                 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5876                         OUR_HANDLE(handle)));
5877                 return WERR_BADFID;
5878         }
5879
5880         if (!get_printer_snum(p, handle, &snum, NULL))
5881                 return WERR_BADFID;
5882
5883         switch (command) {
5884         case SPOOLSS_PRINTER_CONTROL_PAUSE:
5885                 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5886                 break;
5887         case SPOOLSS_PRINTER_CONTROL_RESUME:
5888         case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5889                 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5890                 break;
5891         case SPOOLSS_PRINTER_CONTROL_PURGE:
5892                 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5893                 break;
5894         default:
5895                 return WERR_UNKNOWN_LEVEL;
5896         }
5897
5898         return errcode;
5899 }
5900
5901
5902 /****************************************************************
5903  _spoolss_AbortPrinter
5904  * From MSDN: "Deletes printer's spool file if printer is configured
5905  * for spooling"
5906 ****************************************************************/
5907
5908 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5909                              struct spoolss_AbortPrinter *r)
5910 {
5911         struct printer_handle   *Printer = find_printer_index_by_hnd(p, r->in.handle);
5912         int             snum;
5913         WERROR          errcode = WERR_OK;
5914
5915         if (!Printer) {
5916                 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5917                         OUR_HANDLE(r->in.handle)));
5918                 return WERR_BADFID;
5919         }
5920
5921         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5922                 return WERR_BADFID;
5923
5924         if (!Printer->document_started) {
5925                 return WERR_SPL_NO_STARTDOC;
5926         }
5927
5928         errcode = print_job_delete(p->session_info,
5929                                    p->msg_ctx,
5930                                    snum,
5931                                    Printer->jobid);
5932
5933         return errcode;
5934 }
5935
5936 /********************************************************************
5937  * called by spoolss_api_setprinter
5938  * when updating a printer description
5939  ********************************************************************/
5940
5941 static WERROR update_printer_sec(struct policy_handle *handle,
5942                                  struct pipes_struct *p,
5943                                  struct sec_desc_buf *secdesc_ctr)
5944 {
5945         struct spoolss_security_descriptor *new_secdesc = NULL;
5946         struct spoolss_security_descriptor *old_secdesc = NULL;
5947         const char *printer;
5948         WERROR result;
5949         int snum;
5950         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5951         struct dcerpc_binding_handle *b;
5952         TALLOC_CTX *tmp_ctx = NULL;
5953
5954         if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5955                 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5956                          OUR_HANDLE(handle)));
5957
5958                 result = WERR_BADFID;
5959                 goto done;
5960         }
5961
5962         if (secdesc_ctr == NULL) {
5963                 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5964                 result = WERR_INVALID_PARAM;
5965                 goto done;
5966         }
5967         printer = lp_const_servicename(snum);
5968
5969         /* Check the user has permissions to change the security
5970            descriptor.  By experimentation with two NT machines, the user
5971            requires Full Access to the printer to change security
5972            information. */
5973
5974         if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5975                 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5976                 result = WERR_ACCESS_DENIED;
5977                 goto done;
5978         }
5979
5980         tmp_ctx = talloc_new(p->mem_ctx);
5981         if (!tmp_ctx) {
5982                 return WERR_NOMEM;
5983         }
5984
5985         result = winreg_printer_binding_handle(tmp_ctx,
5986                                                get_session_info_system(),
5987                                                p->msg_ctx,
5988                                                &b);
5989         if (!W_ERROR_IS_OK(result)) {
5990                 goto done;
5991         }
5992
5993         /* NT seems to like setting the security descriptor even though
5994            nothing may have actually changed. */
5995         result = winreg_get_printer_secdesc(tmp_ctx, b,
5996                                             printer,
5997                                             &old_secdesc);
5998         if (!W_ERROR_IS_OK(result)) {
5999                 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6000                 result = WERR_BADFID;
6001                 goto done;
6002         }
6003
6004         if (DEBUGLEVEL >= 10) {
6005                 struct security_acl *the_acl;
6006                 int i;
6007
6008                 the_acl = old_secdesc->dacl;
6009                 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6010                            printer, the_acl->num_aces));
6011
6012                 for (i = 0; i < the_acl->num_aces; i++) {
6013                         DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6014                                            &the_acl->aces[i].trustee),
6015                                   the_acl->aces[i].access_mask));
6016                 }
6017
6018                 the_acl = secdesc_ctr->sd->dacl;
6019
6020                 if (the_acl) {
6021                         DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6022                                    printer, the_acl->num_aces));
6023
6024                         for (i = 0; i < the_acl->num_aces; i++) {
6025                                 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6026                                                    &the_acl->aces[i].trustee),
6027                                            the_acl->aces[i].access_mask));
6028                         }
6029                 } else {
6030                         DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6031                 }
6032         }
6033
6034         new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6035         if (new_secdesc == NULL) {
6036                 result = WERR_NOMEM;
6037                 goto done;
6038         }
6039
6040         if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6041                 result = WERR_OK;
6042                 goto done;
6043         }
6044
6045         result = winreg_set_printer_secdesc(tmp_ctx, b,
6046                                             printer,
6047                                             new_secdesc);
6048
6049 done:
6050         talloc_free(tmp_ctx);
6051         return result;
6052 }
6053
6054 /********************************************************************
6055  Canonicalize printer info from a client
6056  ********************************************************************/
6057
6058 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6059                              struct spoolss_SetPrinterInfo2 *info2,
6060                              int snum)
6061 {
6062         fstring printername;
6063         const char *p;
6064
6065         DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6066                 "portname=%s drivername=%s comment=%s location=%s\n",
6067                 info2->servername, info2->printername, info2->sharename,
6068                 info2->portname, info2->drivername, info2->comment,
6069                 info2->location));
6070
6071         /* we force some elements to "correct" values */
6072         info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6073         if (info2->servername == NULL) {
6074                 return false;
6075         }
6076         info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6077         if (info2->sharename == NULL) {
6078                 return false;
6079         }
6080
6081         /* check to see if we allow printername != sharename */
6082         if (lp_force_printername(snum)) {
6083                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6084                                         lp_netbios_name(), info2->sharename);
6085         } else {
6086                 /* make sure printername is in \\server\printername format */
6087                 fstrcpy(printername, info2->printername);
6088                 p = printername;
6089                 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6090                         if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6091                                 p++;
6092                 }
6093
6094                 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6095                                         lp_netbios_name(), p);
6096         }
6097         if (info2->printername == NULL) {
6098                 return false;
6099         }
6100
6101         info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6102         info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6103
6104         return true;
6105 }
6106
6107 /****************************************************************************
6108 ****************************************************************************/
6109
6110 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6111 {
6112         char *cmd = lp_addport_cmd(talloc_tos());
6113         char *command = NULL;
6114         int ret;
6115         bool is_print_op = false;
6116
6117         if ( !*cmd ) {
6118                 return WERR_ACCESS_DENIED;
6119         }
6120
6121         command = talloc_asprintf(ctx,
6122                         "%s \"%s\" \"%s\"", cmd, portname, uri );
6123         if (!command) {
6124                 return WERR_NOMEM;
6125         }
6126
6127         if ( token )
6128                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6129
6130         DEBUG(10,("Running [%s]\n", command));
6131
6132         /********* BEGIN SePrintOperatorPrivilege **********/
6133
6134         if ( is_print_op )
6135                 become_root();
6136
6137         ret = smbrun(command, NULL);
6138
6139         if ( is_print_op )
6140                 unbecome_root();
6141
6142         /********* END SePrintOperatorPrivilege **********/
6143
6144         DEBUGADD(10,("returned [%d]\n", ret));
6145
6146         TALLOC_FREE(command);
6147
6148         if ( ret != 0 ) {
6149                 return WERR_ACCESS_DENIED;
6150         }
6151
6152         return WERR_OK;
6153 }
6154
6155 /****************************************************************************
6156 ****************************************************************************/
6157
6158 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6159                                    int snum)
6160 {
6161         /*
6162          * As we do not know if we are embedded in the file server process
6163          * or not, we have to pretend that all shares are in use.
6164          */
6165         return true;
6166 }
6167
6168 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6169                              struct spoolss_SetPrinterInfo2 *info2,
6170                              const char *remote_machine,
6171                              struct messaging_context *msg_ctx)
6172 {
6173         char *cmd = lp_addprinter_cmd(talloc_tos());
6174         char **qlines;
6175         char *command = NULL;
6176         int numlines;
6177         int ret;
6178         int fd;
6179         bool is_print_op = false;
6180
6181         if (!remote_machine) {
6182                 return false;
6183         }
6184
6185         command = talloc_asprintf(ctx,
6186                         "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6187                         cmd, info2->printername, info2->sharename,
6188                         info2->portname, info2->drivername,
6189                         info2->location, info2->comment, remote_machine);
6190         if (!command) {
6191                 return false;
6192         }
6193
6194         if ( token )
6195                 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6196
6197         DEBUG(10,("Running [%s]\n", command));
6198
6199         /********* BEGIN SePrintOperatorPrivilege **********/
6200
6201         if ( is_print_op )
6202                 become_root();
6203
6204         if ( (ret = smbrun(command, &fd)) == 0 ) {
6205                 /* Tell everyone we updated smb.conf. */
6206                 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6207         }
6208
6209         if ( is_print_op )
6210                 unbecome_root();
6211
6212         /********* END SePrintOperatorPrivilege **********/
6213
6214         DEBUGADD(10,("returned [%d]\n", ret));
6215
6216         TALLOC_FREE(command);
6217
6218         if ( ret != 0 ) {
6219                 if (fd != -1)
6220                         close(fd);
6221                 return false;
6222         }
6223
6224         /* reload our services immediately */
6225         become_root();
6226         reload_services(NULL, spoolss_conn_snum_used, false);
6227         unbecome_root();
6228
6229         numlines = 0;
6230         /* Get lines and convert them back to dos-codepage */
6231         qlines = fd_lines_load(fd, &numlines, 0, NULL);
6232         DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6233         close(fd);
6234
6235         /* Set the portname to what the script says the portname should be. */
6236         /* but don't require anything to be return from the script exit a good error code */
6237
6238         if (numlines) {
6239                 /* Set the portname to what the script says the portname should be. */
6240                 info2->portname = talloc_strdup(ctx, qlines[0]);
6241                 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6242         }
6243
6244         TALLOC_FREE(qlines);
6245         return true;
6246 }
6247
6248 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6249                                const struct auth_session_info *session_info,
6250                                struct messaging_context *msg_ctx,
6251                                int snum,
6252                                struct spoolss_SetPrinterInfo2 *printer,
6253                                struct spoolss_PrinterInfo2 *old_printer)
6254 {
6255         bool force_update = (old_printer == NULL);
6256         const char *dnsdomname;
6257         const char *longname;
6258         const char *uncname;
6259         const char *spooling;
6260         DATA_BLOB buffer;
6261         WERROR result = WERR_OK;
6262         struct dcerpc_binding_handle *b;
6263         TALLOC_CTX *tmp_ctx;
6264         bool ok;
6265
6266         tmp_ctx = talloc_new(mem_ctx);
6267         if (!tmp_ctx) {
6268                 return WERR_NOMEM;
6269         }
6270
6271         result = winreg_printer_binding_handle(tmp_ctx,
6272                                                session_info,
6273                                                msg_ctx,
6274                                                &b);
6275         if (!W_ERROR_IS_OK(result)) {
6276                 goto done;
6277         }
6278
6279         if (printer->drivername != NULL &&
6280             (force_update ||
6281              !strequal(printer->drivername, old_printer->drivername))) {
6282                 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6283                 if (!ok) {
6284                         DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6285                         result = WERR_INVALID_DATA;
6286                         goto done;
6287                 }
6288                 result = winreg_set_printer_dataex(tmp_ctx, b,
6289                                           printer->sharename,
6290                                           SPOOL_DSSPOOLER_KEY,
6291                                           SPOOL_REG_DRIVERNAME,
6292                                           REG_SZ,
6293                                           buffer.data,
6294                                           buffer.length);
6295                 if (!W_ERROR_IS_OK(result)) {
6296                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6297                         goto done;
6298                 }
6299
6300                 if (!force_update) {
6301                         DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
6302                                 printer->drivername));
6303
6304                         notify_printer_driver(server_event_context(), msg_ctx,
6305                                               snum, printer->drivername ?
6306                                               printer->drivername : "");
6307                 }
6308         }
6309
6310         if (printer->comment != NULL &&
6311             (force_update ||
6312              !strequal(printer->comment, old_printer->comment))) {
6313                 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6314                 if (!ok) {
6315                         DEBUG(0, ("comment data corrupted\n"));
6316                         result = WERR_INVALID_DATA;
6317                         goto done;
6318                 }
6319                 result = winreg_set_printer_dataex(tmp_ctx, b,
6320                                           printer->sharename,
6321                                           SPOOL_DSSPOOLER_KEY,
6322                                           SPOOL_REG_DESCRIPTION,
6323                                           REG_SZ,
6324                                           buffer.data,
6325                                           buffer.length);
6326                 if (!W_ERROR_IS_OK(result)) {
6327                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6328                         goto done;
6329                 }
6330
6331                 if (!force_update) {
6332                         notify_printer_comment(server_event_context(), msg_ctx,
6333                                                snum, printer->comment ?
6334                                                printer->comment : "");
6335                 }
6336         }
6337
6338         if (printer->sharename != NULL &&
6339             (force_update ||
6340              !strequal(printer->sharename, old_printer->sharename))) {
6341                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6342                 if (!ok) {
6343                         DEBUG(0, ("sharename data corrupted\n"));
6344                         result = WERR_INVALID_DATA;
6345                         goto done;
6346                 }
6347                 result = winreg_set_printer_dataex(tmp_ctx, b,
6348                                           printer->sharename,
6349                                           SPOOL_DSSPOOLER_KEY,
6350                                           SPOOL_REG_PRINTSHARENAME,
6351                                           REG_SZ,
6352                                           buffer.data,
6353                                           buffer.length);
6354                 if (!W_ERROR_IS_OK(result)) {
6355                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6356                         goto done;
6357                 }
6358
6359                 if (!force_update) {
6360                         notify_printer_sharename(server_event_context(),
6361                                                  msg_ctx,
6362                                                  snum, printer->sharename ?
6363                                                  printer->sharename : "");
6364                 }
6365         }
6366
6367         if (printer->printername != NULL &&
6368             (force_update ||
6369              !strequal(printer->printername, old_printer->printername))) {
6370                 const char *p;
6371
6372                 p = strrchr(printer->printername, '\\' );
6373                 if (p != NULL) {
6374                         p++;
6375                 } else {
6376                         p = printer->printername;
6377                 }
6378
6379                 ok = push_reg_sz(tmp_ctx, &buffer, p);
6380                 if (!ok) {
6381                         DEBUG(0, ("printername data corrupted\n"));
6382                         result = WERR_INVALID_DATA;
6383                         goto done;
6384                 }
6385                 result = winreg_set_printer_dataex(tmp_ctx, b,
6386                                           printer->sharename,
6387                                           SPOOL_DSSPOOLER_KEY,
6388                                           SPOOL_REG_PRINTERNAME,
6389                                           REG_SZ,
6390                                           buffer.data,
6391                                           buffer.length);
6392                 if (!W_ERROR_IS_OK(result)) {
6393                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6394                         goto done;
6395                 }
6396
6397                 if (!force_update) {
6398                         notify_printer_printername(server_event_context(),
6399                                                    msg_ctx, snum, p ? p : "");
6400                 }
6401         }
6402
6403         if (printer->portname != NULL &&
6404             (force_update ||
6405              !strequal(printer->portname, old_printer->portname))) {
6406                 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6407                 if (!ok) {
6408                         DEBUG(0, ("portname data corrupted\n"));
6409                         result = WERR_INVALID_DATA;
6410                         goto done;
6411                 }
6412                 result = winreg_set_printer_dataex(tmp_ctx, b,
6413                                           printer->sharename,
6414                                           SPOOL_DSSPOOLER_KEY,
6415                                           SPOOL_REG_PORTNAME,
6416                                           REG_SZ,
6417                                           buffer.data,
6418                                           buffer.length);
6419                 if (!W_ERROR_IS_OK(result)) {
6420                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6421                         goto done;
6422                 }
6423
6424                 if (!force_update) {
6425                         notify_printer_port(server_event_context(),
6426                                             msg_ctx, snum, printer->portname ?
6427                                             printer->portname : "");
6428                 }
6429         }
6430
6431         if (printer->location != NULL &&
6432             (force_update ||
6433              !strequal(printer->location, old_printer->location))) {
6434                 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6435                 if (!ok) {
6436                         DEBUG(0, ("location data corrupted\n"));
6437                         result = WERR_INVALID_DATA;
6438                         goto done;
6439                 }
6440                 result = winreg_set_printer_dataex(tmp_ctx, b,
6441                                           printer->sharename,
6442                                           SPOOL_DSSPOOLER_KEY,
6443                                           SPOOL_REG_LOCATION,
6444                                           REG_SZ,
6445                                           buffer.data,
6446                                           buffer.length);
6447                 if (!W_ERROR_IS_OK(result)) {
6448                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6449                         goto done;
6450                 }
6451
6452                 if (!force_update) {
6453                         notify_printer_location(server_event_context(),
6454                                                 msg_ctx, snum,
6455                                                 printer->location ?
6456                                                 printer->location : "");
6457                 }
6458         }
6459
6460         if (printer->sepfile != NULL &&
6461             (force_update ||
6462              !strequal(printer->sepfile, old_printer->sepfile))) {
6463                 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6464                 if (!ok) {
6465                         DEBUG(0, ("sepfile data corrupted\n"));
6466                         result = WERR_INVALID_DATA;
6467                         goto done;
6468                 }
6469                 result = winreg_set_printer_dataex(tmp_ctx, b,
6470                                           printer->sharename,
6471                                           SPOOL_DSSPOOLER_KEY,
6472                                           SPOOL_REG_PRINTSEPARATORFILE,
6473                                           REG_SZ,
6474                                           buffer.data,
6475                                           buffer.length);
6476                 if (!W_ERROR_IS_OK(result)) {
6477                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6478                         goto done;
6479                 }
6480
6481                 if (!force_update) {
6482                         notify_printer_sepfile(server_event_context(),
6483                                                msg_ctx, snum,
6484                                                printer->sepfile ?
6485                                                printer->sepfile : "");
6486                 }
6487         }
6488
6489         if (printer->starttime != 0 &&
6490             (force_update ||
6491              printer->starttime != old_printer->starttime)) {
6492                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6493                 SIVAL(buffer.data, 0, printer->starttime);
6494                 result = winreg_set_printer_dataex(tmp_ctx, b,
6495                                           printer->sharename,
6496                                           SPOOL_DSSPOOLER_KEY,
6497                                           SPOOL_REG_PRINTSTARTTIME,
6498                                           REG_DWORD,
6499                                           buffer.data,
6500                                           buffer.length);
6501                 if (!W_ERROR_IS_OK(result)) {
6502                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6503                         goto done;
6504                 }
6505         }
6506
6507         if (printer->untiltime != 0 &&
6508             (force_update ||
6509              printer->untiltime != old_printer->untiltime)) {
6510                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6511                 SIVAL(buffer.data, 0, printer->untiltime);
6512                 result = winreg_set_printer_dataex(tmp_ctx, b,
6513                                           printer->sharename,
6514                                           SPOOL_DSSPOOLER_KEY,
6515                                           SPOOL_REG_PRINTENDTIME,
6516                                           REG_DWORD,
6517                                           buffer.data,
6518                                           buffer.length);
6519                 if (!W_ERROR_IS_OK(result)) {
6520                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6521                         goto done;
6522                 }
6523         }
6524
6525         if (force_update || printer->priority != old_printer->priority) {
6526                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6527                 SIVAL(buffer.data, 0, printer->priority);
6528                 result = winreg_set_printer_dataex(tmp_ctx, b,
6529                                           printer->sharename,
6530                                           SPOOL_DSSPOOLER_KEY,
6531                                           SPOOL_REG_PRIORITY,
6532                                           REG_DWORD,
6533                                           buffer.data,
6534                                           buffer.length);
6535                 if (!W_ERROR_IS_OK(result)) {
6536                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6537                         goto done;
6538                 }
6539         }
6540
6541         if (force_update || printer->attributes != old_printer->attributes) {
6542                 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6543                 SIVAL(buffer.data, 0, (printer->attributes &
6544                                        PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6545                 result = winreg_set_printer_dataex(tmp_ctx, b,
6546                                           printer->sharename,
6547                                           SPOOL_DSSPOOLER_KEY,
6548                                           SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6549                                           REG_DWORD,
6550                                           buffer.data,
6551                                           buffer.length);
6552                 if (!W_ERROR_IS_OK(result)) {
6553                         DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6554                         goto done;
6555                 }
6556
6557                 switch (printer->attributes & 0x3) {
6558                         case 0:
6559                                 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6560                                 break;
6561                         case 1:
6562                                 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6563                                 break;
6564                         case 2:
6565                                 spooling = SPOOL_REGVAL_PRINTDIRECT;
6566                                 break;
6567                         default:
6568                                 spooling = "unknown";
6569                 }
6570                 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6571                 if (!ok) {
6572                         DEBUG(0, ("printSpooling data corrupted\n"));
6573                         result = WERR_INVALID_DATA;
6574                         goto done;
6575                 }
6576                 winreg_set_printer_dataex(tmp_ctx, b,
6577                                           printer->sharename,
6578                                           SPOOL_DSSPOOLER_KEY,
6579                                           SPOOL_REG_PRINTSPOOLING,
6580                                           REG_SZ,
6581                                           buffer.data,
6582                                           buffer.length);
6583         }
6584
6585         ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6586         if (!ok) {
6587                 DEBUG(0, ("shortServerName data corrupted\n"));
6588                 result = WERR_INVALID_DATA;
6589                 goto done;
6590         }
6591         result = winreg_set_printer_dataex(tmp_ctx, b,
6592                                   printer->sharename,
6593                                   SPOOL_DSSPOOLER_KEY,
6594                                   SPOOL_REG_SHORTSERVERNAME,
6595                                   REG_SZ,
6596                                   buffer.data,
6597                                   buffer.length);
6598         if (!W_ERROR_IS_OK(result)) {
6599                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6600                 goto done;
6601         }
6602
6603         dnsdomname = get_mydnsfullname();
6604         if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6605                 longname = talloc_strdup(tmp_ctx, dnsdomname);
6606         } else {
6607                 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6608         }
6609         if (longname == NULL) {
6610                 result = WERR_NOMEM;
6611                 goto done;
6612         }
6613
6614         ok = push_reg_sz(tmp_ctx, &buffer, longname);
6615         if (!ok) {
6616                 DEBUG(0, ("longname data corrupted\n"));
6617                 result = WERR_INVALID_DATA;
6618                 goto done;
6619         }
6620         result = winreg_set_printer_dataex(tmp_ctx, b,
6621                                            printer->sharename,
6622                                            SPOOL_DSSPOOLER_KEY,
6623                                            SPOOL_REG_SERVERNAME,
6624                                            REG_SZ,
6625                                            buffer.data,
6626                                            buffer.length);
6627         if (!W_ERROR_IS_OK(result)) {
6628                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6629                 goto done;
6630         }
6631
6632         uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6633                                   lp_netbios_name(), printer->sharename);
6634         ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6635         if (!ok) {
6636                 DEBUG(0, ("uncName data corrupted\n"));
6637                 result = WERR_INVALID_DATA;
6638                 goto done;
6639         }
6640         result = winreg_set_printer_dataex(tmp_ctx, b,
6641                                   printer->sharename,
6642                                   SPOOL_DSSPOOLER_KEY,
6643                                   SPOOL_REG_UNCNAME,
6644                                   REG_SZ,
6645                                   buffer.data,
6646                                   buffer.length);
6647         if (!W_ERROR_IS_OK(result)) {
6648                 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6649                 goto done;
6650         }
6651
6652 done:
6653         talloc_free(tmp_ctx);
6654         return result;
6655 }
6656
6657 /********************************************************************
6658  * Called by spoolss_api_setprinter
6659  * when updating a printer description.
6660  ********************************************************************/
6661
6662 static WERROR update_printer(struct pipes_struct *p,
6663                              struct policy_handle *handle,
6664                              struct spoolss_SetPrinterInfoCtr *info_ctr,
6665                              struct spoolss_DeviceMode *devmode)
6666 {
6667         uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6668         struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6669         struct spoolss_PrinterInfo2 *old_printer;
6670         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6671         int snum;
6672         WERROR result = WERR_OK;
6673         TALLOC_CTX *tmp_ctx;
6674         struct dcerpc_binding_handle *b;
6675
6676         DEBUG(8,("update_printer\n"));
6677
6678         tmp_ctx = talloc_new(p->mem_ctx);
6679         if (tmp_ctx == NULL) {
6680                 return WERR_NOMEM;
6681         }
6682
6683         if (!Printer) {
6684                 result = WERR_BADFID;
6685                 goto done;
6686         }
6687
6688         if (!get_printer_snum(p, handle, &snum, NULL)) {
6689                 result = WERR_BADFID;
6690                 goto done;
6691         }
6692
6693         result = winreg_printer_binding_handle(tmp_ctx,
6694                                                get_session_info_system(),
6695                                                p->msg_ctx,
6696                                                &b);
6697         if (!W_ERROR_IS_OK(result)) {
6698                 goto done;
6699         }
6700
6701         result = winreg_get_printer(tmp_ctx, b,
6702                                     lp_const_servicename(snum),
6703                                     &old_printer);
6704         if (!W_ERROR_IS_OK(result)) {
6705                 result = WERR_BADFID;
6706                 goto done;
6707         }
6708
6709         /* Do sanity check on the requested changes for Samba */
6710         if (!check_printer_ok(tmp_ctx, printer, snum)) {
6711                 result = WERR_INVALID_PARAM;
6712                 goto done;
6713         }
6714
6715         /* FIXME!!! If the driver has changed we really should verify that
6716            it is installed before doing much else   --jerry */
6717
6718         /* Check calling user has permission to update printer description */
6719         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6720                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6721                 result = WERR_ACCESS_DENIED;
6722                 goto done;
6723         }
6724
6725         /* Call addprinter hook */
6726         /* Check changes to see if this is really needed */
6727
6728         if (*lp_addprinter_cmd(talloc_tos()) &&
6729                         (!strequal(printer->drivername, old_printer->drivername) ||
6730                          !strequal(printer->comment, old_printer->comment) ||
6731                          !strequal(printer->portname, old_printer->portname) ||
6732                          !strequal(printer->location, old_printer->location)) )
6733         {
6734                 char *raddr;
6735
6736                 raddr = tsocket_address_inet_addr_string(p->remote_address,
6737                                                          p->mem_ctx);
6738                 if (raddr == NULL) {
6739                         return WERR_NOMEM;
6740                 }
6741
6742                 /* add_printer_hook() will call reload_services() */
6743                 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6744                                       printer, raddr,
6745                                       p->msg_ctx)) {
6746                         result = WERR_ACCESS_DENIED;
6747                         goto done;
6748                 }
6749         }
6750
6751         result = update_dsspooler(tmp_ctx,
6752                                   get_session_info_system(),
6753                                   p->msg_ctx,
6754                                   snum,
6755                                   printer,
6756                                   old_printer);
6757         if (!W_ERROR_IS_OK(result)) {
6758                 goto done;
6759         }
6760
6761         printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6762
6763         if (devmode == NULL) {
6764                 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6765         }
6766         result = winreg_update_printer(tmp_ctx, b,
6767                                        printer->sharename,
6768                                        printer_mask,
6769                                        printer,
6770                                        devmode,
6771                                        NULL);
6772
6773 done:
6774         talloc_free(tmp_ctx);
6775
6776         return result;
6777 }
6778
6779 /****************************************************************************
6780 ****************************************************************************/
6781 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6782                                            struct policy_handle *handle,
6783                                            struct spoolss_SetPrinterInfo7 *info7)
6784 {
6785 #ifdef HAVE_ADS
6786         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6787         WERROR result;
6788         int snum;
6789         struct printer_handle *Printer;
6790
6791         if ( lp_security() != SEC_ADS ) {
6792                 return WERR_UNKNOWN_LEVEL;
6793         }
6794
6795         Printer = find_printer_index_by_hnd(p, handle);
6796
6797         DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6798
6799         if (!Printer)
6800                 return WERR_BADFID;
6801
6802         if (!get_printer_snum(p, handle, &snum, NULL))
6803                 return WERR_BADFID;
6804
6805         result = winreg_get_printer_internal(p->mem_ctx,
6806                                     get_session_info_system(),
6807                                     p->msg_ctx,
6808                                     lp_servicename(talloc_tos(), snum),
6809                                     &pinfo2);
6810         if (!W_ERROR_IS_OK(result)) {
6811                 return WERR_BADFID;
6812         }
6813
6814         nt_printer_publish(pinfo2,
6815                            get_session_info_system(),
6816                            p->msg_ctx,
6817                            pinfo2,
6818                            info7->action);
6819
6820         TALLOC_FREE(pinfo2);
6821         return WERR_OK;
6822 #else
6823         return WERR_UNKNOWN_LEVEL;
6824 #endif
6825 }
6826
6827 /********************************************************************
6828  ********************************************************************/
6829
6830 static WERROR update_printer_devmode(struct pipes_struct *p,
6831                                      struct policy_handle *handle,
6832                                      struct spoolss_DeviceMode *devmode)
6833 {
6834         int snum;
6835         struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6836         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6837
6838         DEBUG(8,("update_printer_devmode\n"));
6839
6840         if (!Printer) {
6841                 return WERR_BADFID;
6842         }
6843
6844         if (!get_printer_snum(p, handle, &snum, NULL)) {
6845                 return WERR_BADFID;
6846         }
6847
6848         /* Check calling user has permission to update printer description */
6849         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6850                 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6851                 return WERR_ACCESS_DENIED;
6852         }
6853
6854         return winreg_update_printer_internal(p->mem_ctx,
6855                                      get_session_info_system(),
6856                                      p->msg_ctx,
6857                                      lp_const_servicename(snum),
6858                                      info2_mask,
6859                                      NULL,
6860                                      devmode,
6861                                      NULL);
6862 }
6863
6864
6865 /****************************************************************
6866  _spoolss_SetPrinter
6867 ****************************************************************/
6868
6869 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6870                            struct spoolss_SetPrinter *r)
6871 {
6872         WERROR result;
6873
6874         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6875
6876         if (!Printer) {
6877                 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6878                         OUR_HANDLE(r->in.handle)));
6879                 return WERR_BADFID;
6880         }
6881
6882         /* check the level */
6883         switch (r->in.info_ctr->level) {
6884                 case 0:
6885                         return control_printer(r->in.handle, r->in.command, p);
6886                 case 2:
6887                         result = update_printer(p, r->in.handle,
6888                                                 r->in.info_ctr,
6889                                                 r->in.devmode_ctr->devmode);
6890                         if (!W_ERROR_IS_OK(result))
6891                                 return result;
6892                         if (r->in.secdesc_ctr->sd)
6893                                 result = update_printer_sec(r->in.handle, p,
6894                                                             r->in.secdesc_ctr);
6895                         return result;
6896                 case 3:
6897                         return update_printer_sec(r->in.handle, p,
6898                                                   r->in.secdesc_ctr);
6899                 case 7:
6900                         return publish_or_unpublish_printer(p, r->in.handle,
6901                                                             r->in.info_ctr->info.info7);
6902                 case 8:
6903                         return update_printer_devmode(p, r->in.handle,
6904                                                       r->in.devmode_ctr->devmode);
6905                 default:
6906                         return WERR_UNKNOWN_LEVEL;
6907         }
6908 }
6909
6910 /****************************************************************
6911  _spoolss_FindClosePrinterNotify
6912 ****************************************************************/
6913
6914 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6915                                        struct spoolss_FindClosePrinterNotify *r)
6916 {
6917         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6918
6919         if (!Printer) {
6920                 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6921                         "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6922                 return WERR_BADFID;
6923         }
6924
6925         if (Printer->notify.cli_chan != NULL &&
6926             Printer->notify.cli_chan->active_connections > 0) {
6927                 int snum = -1;
6928
6929                 if (Printer->printer_type == SPLHND_PRINTER) {
6930                         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6931                                 return WERR_BADFID;
6932                         }
6933                 }
6934
6935                 srv_spoolss_replycloseprinter(snum, Printer);
6936         }
6937
6938         Printer->notify.flags=0;
6939         Printer->notify.options=0;
6940         Printer->notify.localmachine[0]='\0';
6941         Printer->notify.printerlocal=0;
6942         TALLOC_FREE(Printer->notify.option);
6943
6944         return WERR_OK;
6945 }
6946
6947 /****************************************************************
6948  _spoolss_AddJob
6949 ****************************************************************/
6950
6951 WERROR _spoolss_AddJob(struct pipes_struct *p,
6952                        struct spoolss_AddJob *r)
6953 {
6954         if (!r->in.buffer && (r->in.offered != 0)) {
6955                 return WERR_INVALID_PARAM;
6956         }
6957
6958         /* this is what a NT server returns for AddJob. AddJob must fail on
6959          * non-local printers */
6960
6961         if (r->in.level != 1) {
6962                 return WERR_UNKNOWN_LEVEL;
6963         }
6964
6965         return WERR_INVALID_PARAM;
6966 }
6967
6968 /****************************************************************************
6969 fill_job_info1
6970 ****************************************************************************/
6971
6972 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6973                              struct spoolss_JobInfo1 *r,
6974                              const print_queue_struct *queue,
6975                              int position, int snum,
6976                              struct spoolss_PrinterInfo2 *pinfo2)
6977 {
6978         struct tm *t;
6979
6980         t = gmtime(&queue->time);
6981
6982         r->job_id               = queue->sysjob;
6983
6984         r->printer_name         = lp_servicename(mem_ctx, snum);
6985         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6986         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
6987         W_ERROR_HAVE_NO_MEMORY(r->server_name);
6988         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
6989         W_ERROR_HAVE_NO_MEMORY(r->user_name);
6990         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
6991         W_ERROR_HAVE_NO_MEMORY(r->document_name);
6992         r->data_type            = talloc_strdup(mem_ctx, "RAW");
6993         W_ERROR_HAVE_NO_MEMORY(r->data_type);
6994         r->text_status          = talloc_strdup(mem_ctx, "");
6995         W_ERROR_HAVE_NO_MEMORY(r->text_status);
6996
6997         r->status               = nt_printj_status(queue->status);
6998         r->priority             = queue->priority;
6999         r->position             = position;
7000         r->total_pages          = queue->page_count;
7001         r->pages_printed        = 0; /* ??? */
7002
7003         init_systemtime(&r->submitted, t);
7004
7005         return WERR_OK;
7006 }
7007
7008 /****************************************************************************
7009 fill_job_info2
7010 ****************************************************************************/
7011
7012 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7013                              struct spoolss_JobInfo2 *r,
7014                              const print_queue_struct *queue,
7015                              int position, int snum,
7016                              struct spoolss_PrinterInfo2 *pinfo2,
7017                              struct spoolss_DeviceMode *devmode)
7018 {
7019         struct tm *t;
7020
7021         t = gmtime(&queue->time);
7022
7023         r->job_id               = queue->sysjob;
7024
7025         r->printer_name         = lp_servicename(mem_ctx, snum);
7026         W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7027         r->server_name          = talloc_strdup(mem_ctx, pinfo2->servername);
7028         W_ERROR_HAVE_NO_MEMORY(r->server_name);
7029         r->user_name            = talloc_strdup(mem_ctx, queue->fs_user);
7030         W_ERROR_HAVE_NO_MEMORY(r->user_name);
7031         r->document_name        = talloc_strdup(mem_ctx, queue->fs_file);
7032         W_ERROR_HAVE_NO_MEMORY(r->document_name);
7033         r->notify_name          = talloc_strdup(mem_ctx, queue->fs_user);
7034         W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7035         r->data_type            = talloc_strdup(mem_ctx, "RAW");
7036         W_ERROR_HAVE_NO_MEMORY(r->data_type);
7037         r->print_processor      = talloc_strdup(mem_ctx, "winprint");
7038         W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7039         r->parameters           = talloc_strdup(mem_ctx, "");
7040         W_ERROR_HAVE_NO_MEMORY(r->parameters);
7041         r->driver_name          = talloc_strdup(mem_ctx, pinfo2->drivername);
7042         W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7043
7044         r->devmode              = devmode;
7045
7046         r->text_status          = talloc_strdup(mem_ctx, "");
7047         W_ERROR_HAVE_NO_MEMORY(r->text_status);
7048
7049         r->secdesc              = NULL;
7050
7051         r->status               = nt_printj_status(queue->status);
7052         r->priority             = queue->priority;
7053         r->position             = position;
7054         r->start_time           = 0;
7055         r->until_time           = 0;
7056         r->total_pages          = queue->page_count;
7057         r->size                 = queue->size;
7058         init_systemtime(&r->submitted, t);
7059         r->time                 = 0;
7060         r->pages_printed        = 0; /* ??? */
7061
7062         return WERR_OK;
7063 }
7064
7065 /****************************************************************************
7066 fill_job_info3
7067 ****************************************************************************/
7068
7069 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7070                              struct spoolss_JobInfo3 *r,
7071                              const print_queue_struct *queue,
7072                              const print_queue_struct *next_queue,
7073                              int position, int snum,
7074                              struct spoolss_PrinterInfo2 *pinfo2)
7075 {
7076         r->job_id               = queue->sysjob;
7077         r->next_job_id          = 0;
7078         if (next_queue) {
7079                 r->next_job_id  = next_queue->sysjob;
7080         }
7081         r->reserved             = 0;
7082
7083         return WERR_OK;
7084 }
7085
7086 /****************************************************************************
7087  Enumjobs at level 1.
7088 ****************************************************************************/
7089
7090 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7091                               const print_queue_struct *queue,
7092                               uint32_t num_queues, int snum,
7093                               struct spoolss_PrinterInfo2 *pinfo2,
7094                               union spoolss_JobInfo **info_p,
7095                               uint32_t *count)
7096 {
7097         union spoolss_JobInfo *info;
7098         int i;
7099         WERROR result = WERR_OK;
7100
7101         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7102         W_ERROR_HAVE_NO_MEMORY(info);
7103
7104         *count = num_queues;
7105
7106         for (i=0; i<*count; i++) {
7107                 result = fill_job_info1(info,
7108                                         &info[i].info1,
7109                                         &queue[i],
7110                                         i,
7111                                         snum,
7112                                         pinfo2);
7113                 if (!W_ERROR_IS_OK(result)) {
7114                         goto out;
7115                 }
7116         }
7117
7118  out:
7119         if (!W_ERROR_IS_OK(result)) {
7120                 TALLOC_FREE(info);
7121                 *count = 0;
7122                 return result;
7123         }
7124
7125         *info_p = info;
7126
7127         return WERR_OK;
7128 }
7129
7130 /****************************************************************************
7131  Enumjobs at level 2.
7132 ****************************************************************************/
7133
7134 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7135                               const print_queue_struct *queue,
7136                               uint32_t num_queues, int snum,
7137                               struct spoolss_PrinterInfo2 *pinfo2,
7138                               union spoolss_JobInfo **info_p,
7139                               uint32_t *count)
7140 {
7141         union spoolss_JobInfo *info;
7142         int i;
7143         WERROR result = WERR_OK;
7144
7145         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7146         W_ERROR_HAVE_NO_MEMORY(info);
7147
7148         *count = num_queues;
7149
7150         for (i=0; i<*count; i++) {
7151                 struct spoolss_DeviceMode *devmode;
7152
7153                 result = spoolss_create_default_devmode(info,
7154                                                         pinfo2->printername,
7155                                                         &devmode);
7156                 if (!W_ERROR_IS_OK(result)) {
7157                         DEBUG(3, ("Can't proceed w/o a devmode!"));
7158                         goto out;
7159                 }
7160
7161                 result = fill_job_info2(info,
7162                                         &info[i].info2,
7163                                         &queue[i],
7164                                         i,
7165                                         snum,
7166                                         pinfo2,
7167                                         devmode);
7168                 if (!W_ERROR_IS_OK(result)) {
7169                         goto out;
7170                 }
7171         }
7172
7173  out:
7174         if (!W_ERROR_IS_OK(result)) {
7175                 TALLOC_FREE(info);
7176                 *count = 0;
7177                 return result;
7178         }
7179
7180         *info_p = info;
7181
7182         return WERR_OK;
7183 }
7184
7185 /****************************************************************************
7186  Enumjobs at level 3.
7187 ****************************************************************************/
7188
7189 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7190                               const print_queue_struct *queue,
7191                               uint32_t num_queues, int snum,
7192                               struct spoolss_PrinterInfo2 *pinfo2,
7193                               union spoolss_JobInfo **info_p,
7194                               uint32_t *count)
7195 {
7196         union spoolss_JobInfo *info;
7197         int i;
7198         WERROR result = WERR_OK;
7199
7200         info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7201         W_ERROR_HAVE_NO_MEMORY(info);
7202
7203         *count = num_queues;
7204
7205         for (i=0; i<*count; i++) {
7206                 const print_queue_struct *next_queue = NULL;
7207
7208                 if (i+1 < *count) {
7209                         next_queue = &queue[i+1];
7210                 }
7211
7212                 result = fill_job_info3(info,
7213                                         &info[i].info3,
7214                                         &queue[i],
7215                                         next_queue,
7216                                         i,
7217                                         snum,
7218                                         pinfo2);
7219                 if (!W_ERROR_IS_OK(result)) {
7220                         goto out;
7221                 }
7222         }
7223
7224  out:
7225         if (!W_ERROR_IS_OK(result)) {
7226                 TALLOC_FREE(info);
7227                 *count = 0;
7228                 return result;
7229         }
7230
7231         *info_p = info;
7232
7233         return WERR_OK;
7234 }
7235
7236 /****************************************************************
7237  _spoolss_EnumJobs
7238 ****************************************************************/
7239
7240 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7241                          struct spoolss_EnumJobs *r)
7242 {
7243         WERROR result;
7244         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7245         int snum;
7246         print_status_struct prt_status;
7247         print_queue_struct *queue = NULL;
7248         uint32_t count;
7249
7250         /* that's an [in out] buffer */
7251
7252         if (!r->in.buffer && (r->in.offered != 0)) {
7253                 return WERR_INVALID_PARAM;
7254         }
7255
7256         DEBUG(4,("_spoolss_EnumJobs\n"));
7257
7258         *r->out.needed = 0;
7259         *r->out.count = 0;
7260         *r->out.info = NULL;
7261
7262         /* lookup the printer snum and tdb entry */
7263
7264         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7265                 return WERR_BADFID;
7266         }
7267
7268         result = winreg_get_printer_internal(p->mem_ctx,
7269                                     get_session_info_system(),
7270                                     p->msg_ctx,
7271                                     lp_const_servicename(snum),
7272                                     &pinfo2);
7273         if (!W_ERROR_IS_OK(result)) {
7274                 return result;
7275         }
7276
7277         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7278         DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7279                 count, prt_status.status, prt_status.message));
7280
7281         if (count == 0) {
7282                 SAFE_FREE(queue);
7283                 TALLOC_FREE(pinfo2);
7284                 return WERR_OK;
7285         }
7286
7287         switch (r->in.level) {
7288         case 1:
7289                 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7290                                          pinfo2, r->out.info, r->out.count);
7291                 break;
7292         case 2:
7293                 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7294                                          pinfo2, r->out.info, r->out.count);
7295                 break;
7296         case 3:
7297                 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7298                                          pinfo2, r->out.info, r->out.count);
7299                 break;
7300         default:
7301                 result = WERR_UNKNOWN_LEVEL;
7302                 break;
7303         }
7304
7305         SAFE_FREE(queue);
7306         TALLOC_FREE(pinfo2);
7307
7308         if (!W_ERROR_IS_OK(result)) {
7309                 return result;
7310         }
7311
7312         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7313                                                      spoolss_EnumJobs,
7314                                                      *r->out.info, r->in.level,
7315                                                      *r->out.count);
7316         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7317         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7318
7319         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7320 }
7321
7322 /****************************************************************
7323  _spoolss_ScheduleJob
7324 ****************************************************************/
7325
7326 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7327                             struct spoolss_ScheduleJob *r)
7328 {
7329         return WERR_OK;
7330 }
7331
7332 /****************************************************************
7333 ****************************************************************/
7334
7335 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7336                                struct messaging_context *msg_ctx,
7337                                const char *printer_name,
7338                                uint32_t job_id,
7339                                struct spoolss_SetJobInfo1 *r)
7340 {
7341         char *old_doc_name;
7342
7343         if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7344                 return WERR_BADFID;
7345         }
7346
7347         if (strequal(old_doc_name, r->document_name)) {
7348                 return WERR_OK;
7349         }
7350
7351         if (!print_job_set_name(server_event_context(), msg_ctx,
7352                                 printer_name, job_id, r->document_name)) {
7353                 return WERR_BADFID;
7354         }
7355
7356         return WERR_OK;
7357 }
7358
7359 /****************************************************************
7360  _spoolss_SetJob
7361 ****************************************************************/
7362
7363 WERROR _spoolss_SetJob(struct pipes_struct *p,
7364                        struct spoolss_SetJob *r)
7365 {
7366         const struct auth_session_info *session_info = p->session_info;
7367         int snum;
7368         WERROR errcode = WERR_BADFUNC;
7369
7370         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7371                 return WERR_BADFID;
7372         }
7373
7374         if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7375                 return WERR_INVALID_PRINTER_NAME;
7376         }
7377
7378         switch (r->in.command) {
7379         case SPOOLSS_JOB_CONTROL_CANCEL:
7380         case SPOOLSS_JOB_CONTROL_DELETE:
7381                 errcode = print_job_delete(session_info, p->msg_ctx,
7382                                            snum, r->in.job_id);
7383                 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7384                         errcode = WERR_OK;
7385                 }
7386                 break;
7387         case SPOOLSS_JOB_CONTROL_PAUSE:
7388                 errcode = print_job_pause(session_info, p->msg_ctx,
7389                                           snum, r->in.job_id);
7390                 break;
7391         case SPOOLSS_JOB_CONTROL_RESTART:
7392         case SPOOLSS_JOB_CONTROL_RESUME:
7393                 errcode = print_job_resume(session_info, p->msg_ctx,
7394                                            snum, r->in.job_id);
7395                 break;
7396         case 0:
7397                 errcode = WERR_OK;
7398                 break;
7399         default:
7400                 return WERR_UNKNOWN_LEVEL;
7401         }
7402
7403         if (!W_ERROR_IS_OK(errcode)) {
7404                 return errcode;
7405         }
7406
7407         if (r->in.ctr == NULL) {
7408                 return errcode;
7409         }
7410
7411         switch (r->in.ctr->level) {
7412         case 1:
7413                 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7414                                            lp_const_servicename(snum),
7415                                            r->in.job_id,
7416                                            r->in.ctr->info.info1);
7417                 break;
7418         case 2:
7419         case 3:
7420         case 4:
7421         default:
7422                 return WERR_UNKNOWN_LEVEL;
7423         }
7424
7425         return errcode;
7426 }
7427
7428 /****************************************************************************
7429  Enumerates all printer drivers by level and architecture.
7430 ****************************************************************************/
7431
7432 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7433                                                        const struct auth_session_info *session_info,
7434                                                        struct messaging_context *msg_ctx,
7435                                                        const char *servername,
7436                                                        const char *architecture,
7437                                                        uint32_t level,
7438                                                        union spoolss_DriverInfo **info_p,
7439                                                        uint32_t *count_p)
7440 {
7441         int i;
7442         uint32_t version;
7443         struct spoolss_DriverInfo8 *driver;
7444         union spoolss_DriverInfo *info = NULL;
7445         uint32_t count = 0;
7446         WERROR result = WERR_OK;
7447         uint32_t num_drivers;
7448         const char **drivers;
7449         struct dcerpc_binding_handle *b;
7450         TALLOC_CTX *tmp_ctx = NULL;
7451
7452         *count_p = 0;
7453         *info_p = NULL;
7454
7455         tmp_ctx = talloc_new(mem_ctx);
7456         if (!tmp_ctx) {
7457                 return WERR_NOMEM;
7458         }
7459
7460         result = winreg_printer_binding_handle(tmp_ctx,
7461                                                session_info,
7462                                                msg_ctx,
7463                                                &b);
7464         if (!W_ERROR_IS_OK(result)) {
7465                 goto out;
7466         }
7467
7468         for (version=0; version<DRIVER_MAX_VERSION; version++) {
7469                 result = winreg_get_driver_list(tmp_ctx, b,
7470                                                 architecture, version,
7471                                                 &num_drivers, &drivers);
7472                 if (!W_ERROR_IS_OK(result)) {
7473                         goto out;
7474                 }
7475                 DEBUG(4, ("we have:[%d] drivers in environment"
7476                           " [%s] and version [%d]\n",
7477                           num_drivers, architecture, version));
7478
7479                 if (num_drivers != 0) {
7480                         info = talloc_realloc(tmp_ctx, info,
7481                                                     union spoolss_DriverInfo,
7482                                                     count + num_drivers);
7483                         if (!info) {
7484                                 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7485                                         "failed to enlarge driver info buffer!\n"));
7486                                 result = WERR_NOMEM;
7487                                 goto out;
7488                         }
7489                 }
7490
7491                 for (i = 0; i < num_drivers; i++) {
7492                         DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7493
7494                         result = winreg_get_driver(tmp_ctx, b,
7495                                                    architecture, drivers[i],
7496                                                    version, &driver);
7497                         if (!W_ERROR_IS_OK(result)) {
7498                                 goto out;
7499                         }
7500
7501                         switch (level) {
7502                         case 1:
7503                                 result = fill_printer_driver_info1(info, &info[count+i].info1,
7504                                                                    driver, servername);
7505                                 break;
7506                         case 2:
7507                                 result = fill_printer_driver_info2(info, &info[count+i].info2,
7508                                                                    driver, servername);
7509                                 break;
7510                         case 3:
7511                                 result = fill_printer_driver_info3(info, &info[count+i].info3,
7512                                                                    driver, servername);
7513                                 break;
7514                         case 4:
7515                                 result = fill_printer_driver_info4(info, &info[count+i].info4,
7516                                                                    driver, servername);
7517                                 break;
7518                         case 5:
7519                                 result = fill_printer_driver_info5(info, &info[count+i].info5,
7520                                                                    driver, servername);
7521                                 break;
7522                         case 6:
7523                                 result = fill_printer_driver_info6(info, &info[count+i].info6,
7524                                                                    driver, servername);
7525                                 break;
7526                         case 8:
7527                                 result = fill_printer_driver_info8(info, &info[count+i].info8,
7528                                                                    driver, servername);
7529                                 break;
7530                         default:
7531                                 result = WERR_UNKNOWN_LEVEL;
7532                                 break;
7533                         }
7534
7535                         TALLOC_FREE(driver);
7536
7537                         if (!W_ERROR_IS_OK(result)) {
7538                                 goto out;
7539                         }
7540                 }
7541
7542                 count += num_drivers;
7543                 TALLOC_FREE(drivers);
7544         }
7545
7546 out:
7547         if (W_ERROR_IS_OK(result)) {
7548                 *info_p = talloc_move(mem_ctx, &info);
7549                 *count_p = count;
7550         }
7551
7552         talloc_free(tmp_ctx);
7553         return result;
7554 }
7555
7556 /****************************************************************************
7557  Enumerates all printer drivers by level.
7558 ****************************************************************************/
7559
7560 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7561                                        const struct auth_session_info *session_info,
7562                                        struct messaging_context *msg_ctx,
7563                                        const char *servername,
7564                                        const char *architecture,
7565                                        uint32_t level,
7566                                        union spoolss_DriverInfo **info_p,
7567                                        uint32_t *count_p)
7568 {
7569         uint32_t a,i;
7570         WERROR result = WERR_OK;
7571
7572         if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7573
7574                 for (a=0; archi_table[a].long_archi != NULL; a++) {
7575
7576                         union spoolss_DriverInfo *info = NULL;
7577                         uint32_t count = 0;
7578
7579                         result = enumprinterdrivers_level_by_architecture(mem_ctx,
7580                                                                           session_info,
7581                                                                           msg_ctx,
7582                                                                           servername,
7583                                                                           archi_table[a].long_archi,
7584                                                                           level,
7585                                                                           &info,
7586                                                                           &count);
7587                         if (!W_ERROR_IS_OK(result)) {
7588                                 continue;
7589                         }
7590
7591                         for (i=0; i < count; i++) {
7592                                 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7593                                              info[i], info_p, count_p);
7594                         }
7595                 }
7596
7597                 return result;
7598         }
7599
7600         return enumprinterdrivers_level_by_architecture(mem_ctx,
7601                                                         session_info,
7602                                                         msg_ctx,
7603                                                         servername,
7604                                                         architecture,
7605                                                         level,
7606                                                         info_p,
7607                                                         count_p);
7608 }
7609
7610 /****************************************************************
7611  _spoolss_EnumPrinterDrivers
7612 ****************************************************************/
7613
7614 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7615                                    struct spoolss_EnumPrinterDrivers *r)
7616 {
7617         const char *cservername;
7618         WERROR result;
7619
7620         /* that's an [in out] buffer */
7621
7622         if (!r->in.buffer && (r->in.offered != 0)) {
7623                 return WERR_INVALID_PARAM;
7624         }
7625
7626         DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7627
7628         *r->out.needed = 0;
7629         *r->out.count = 0;
7630         *r->out.info = NULL;
7631
7632         cservername = canon_servername(r->in.server);
7633
7634         if (!is_myname_or_ipaddr(cservername)) {
7635                 return WERR_UNKNOWN_PRINTER_DRIVER;
7636         }
7637
7638         result = enumprinterdrivers_level(p->mem_ctx,
7639                                           get_session_info_system(),
7640                                           p->msg_ctx,
7641                                           cservername,
7642                                           r->in.environment,
7643                                           r->in.level,
7644                                           r->out.info,
7645                                           r->out.count);
7646         if (!W_ERROR_IS_OK(result)) {
7647                 return result;
7648         }
7649
7650         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7651                                                      spoolss_EnumPrinterDrivers,
7652                                                      *r->out.info, r->in.level,
7653                                                      *r->out.count);
7654         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7655         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7656
7657         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7658 }
7659
7660 /****************************************************************
7661  _spoolss_EnumForms
7662 ****************************************************************/
7663
7664 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7665                           struct spoolss_EnumForms *r)
7666 {
7667         WERROR result;
7668
7669         *r->out.count = 0;
7670         *r->out.needed = 0;
7671         *r->out.info = NULL;
7672
7673         /* that's an [in out] buffer */
7674
7675         if (!r->in.buffer && (r->in.offered != 0) ) {
7676                 return WERR_INVALID_PARAM;
7677         }
7678
7679         DEBUG(4,("_spoolss_EnumForms\n"));
7680         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7681         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7682
7683         switch (r->in.level) {
7684         case 1:
7685                 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7686                                                    get_session_info_system(),
7687                                                    p->msg_ctx,
7688                                                    r->out.count,
7689                                                    r->out.info);
7690                 break;
7691         default:
7692                 result = WERR_UNKNOWN_LEVEL;
7693                 break;
7694         }
7695
7696         if (!W_ERROR_IS_OK(result)) {
7697                 return result;
7698         }
7699
7700         if (*r->out.count == 0) {
7701                 return WERR_NO_MORE_ITEMS;
7702         }
7703
7704         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7705                                                      spoolss_EnumForms,
7706                                                      *r->out.info, r->in.level,
7707                                                      *r->out.count);
7708         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7709         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7710
7711         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7712 }
7713
7714 /****************************************************************
7715  _spoolss_GetForm
7716 ****************************************************************/
7717
7718 WERROR _spoolss_GetForm(struct pipes_struct *p,
7719                         struct spoolss_GetForm *r)
7720 {
7721         WERROR result;
7722
7723         /* that's an [in out] buffer */
7724
7725         if (!r->in.buffer && (r->in.offered != 0)) {
7726                 return WERR_INVALID_PARAM;
7727         }
7728
7729         DEBUG(4,("_spoolss_GetForm\n"));
7730         DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7731         DEBUGADD(5,("Info level [%d]\n",          r->in.level));
7732
7733         switch (r->in.level) {
7734         case 1:
7735                 result = winreg_printer_getform1_internal(p->mem_ctx,
7736                                                  get_session_info_system(),
7737                                                  p->msg_ctx,
7738                                                  r->in.form_name,
7739                                                  &r->out.info->info1);
7740                 break;
7741         default:
7742                 result = WERR_UNKNOWN_LEVEL;
7743                 break;
7744         }
7745
7746         if (!W_ERROR_IS_OK(result)) {
7747                 TALLOC_FREE(r->out.info);
7748                 return result;
7749         }
7750
7751         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7752                                                r->out.info, r->in.level);
7753         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7754
7755         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7756 }
7757
7758 /****************************************************************************
7759 ****************************************************************************/
7760
7761 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7762                           struct spoolss_PortInfo1 *r,
7763                           const char *name)
7764 {
7765         r->port_name = talloc_strdup(mem_ctx, name);
7766         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7767
7768         return WERR_OK;
7769 }
7770
7771 /****************************************************************************
7772  TODO: This probably needs distinguish between TCP/IP and Local ports
7773  somehow.
7774 ****************************************************************************/
7775
7776 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7777                           struct spoolss_PortInfo2 *r,
7778                           const char *name)
7779 {
7780         r->port_name = talloc_strdup(mem_ctx, name);
7781         W_ERROR_HAVE_NO_MEMORY(r->port_name);
7782
7783         r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7784         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7785
7786         r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7787         W_ERROR_HAVE_NO_MEMORY(r->description);
7788
7789         r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7790         r->reserved = 0;
7791
7792         return WERR_OK;
7793 }
7794
7795
7796 /****************************************************************************
7797  wrapper around the enumer ports command
7798 ****************************************************************************/
7799
7800 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7801 {
7802         char *cmd = lp_enumports_cmd(talloc_tos());
7803         char **qlines = NULL;
7804         char *command = NULL;
7805         int numlines;
7806         int ret;
7807         int fd;
7808
7809         *count = 0;
7810         *lines = NULL;
7811
7812         /* if no hook then just fill in the default port */
7813
7814         if ( !*cmd ) {
7815                 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7816                         return WERR_NOMEM;
7817                 }
7818                 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7819                         TALLOC_FREE(qlines);
7820                         return WERR_NOMEM;
7821                 }
7822                 qlines[1] = NULL;
7823                 numlines = 1;
7824         }
7825         else {
7826                 /* we have a valid enumport command */
7827
7828                 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7829                 if (!command) {
7830                         return WERR_NOMEM;
7831                 }
7832
7833                 DEBUG(10,("Running [%s]\n", command));
7834                 ret = smbrun(command, &fd);
7835                 DEBUG(10,("Returned [%d]\n", ret));
7836                 TALLOC_FREE(command);
7837                 if (ret != 0) {
7838                         if (fd != -1) {
7839                                 close(fd);
7840                         }
7841                         return WERR_ACCESS_DENIED;
7842                 }
7843
7844                 numlines = 0;
7845                 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7846                 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7847                 close(fd);
7848         }
7849
7850         *count = numlines;
7851         *lines = qlines;
7852
7853         return WERR_OK;
7854 }
7855
7856 /****************************************************************************
7857  enumports level 1.
7858 ****************************************************************************/
7859
7860 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7861                                 union spoolss_PortInfo **info_p,
7862                                 uint32_t *count)
7863 {
7864         union spoolss_PortInfo *info = NULL;
7865         int i=0;
7866         WERROR result = WERR_OK;
7867         char **qlines = NULL;
7868         int numlines = 0;
7869
7870         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7871         if (!W_ERROR_IS_OK(result)) {
7872                 goto out;
7873         }
7874
7875         if (numlines) {
7876                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7877                 if (!info) {
7878                         DEBUG(10,("Returning WERR_NOMEM\n"));
7879                         result = WERR_NOMEM;
7880                         goto out;
7881                 }
7882
7883                 for (i=0; i<numlines; i++) {
7884                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7885                         result = fill_port_1(info, &info[i].info1, qlines[i]);
7886                         if (!W_ERROR_IS_OK(result)) {
7887                                 goto out;
7888                         }
7889                 }
7890         }
7891         TALLOC_FREE(qlines);
7892
7893 out:
7894         if (!W_ERROR_IS_OK(result)) {
7895                 TALLOC_FREE(info);
7896                 TALLOC_FREE(qlines);
7897                 *count = 0;
7898                 *info_p = NULL;
7899                 return result;
7900         }
7901
7902         *info_p = info;
7903         *count = numlines;
7904
7905         return WERR_OK;
7906 }
7907
7908 /****************************************************************************
7909  enumports level 2.
7910 ****************************************************************************/
7911
7912 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7913                                 union spoolss_PortInfo **info_p,
7914                                 uint32_t *count)
7915 {
7916         union spoolss_PortInfo *info = NULL;
7917         int i=0;
7918         WERROR result = WERR_OK;
7919         char **qlines = NULL;
7920         int numlines = 0;
7921
7922         result = enumports_hook(talloc_tos(), &numlines, &qlines );
7923         if (!W_ERROR_IS_OK(result)) {
7924                 goto out;
7925         }
7926
7927         if (numlines) {
7928                 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7929                 if (!info) {
7930                         DEBUG(10,("Returning WERR_NOMEM\n"));
7931                         result = WERR_NOMEM;
7932                         goto out;
7933                 }
7934
7935                 for (i=0; i<numlines; i++) {
7936                         DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7937                         result = fill_port_2(info, &info[i].info2, qlines[i]);
7938                         if (!W_ERROR_IS_OK(result)) {
7939                                 goto out;
7940                         }
7941                 }
7942         }
7943         TALLOC_FREE(qlines);
7944
7945 out:
7946         if (!W_ERROR_IS_OK(result)) {
7947                 TALLOC_FREE(info);
7948                 TALLOC_FREE(qlines);
7949                 *count = 0;
7950                 *info_p = NULL;
7951                 return result;
7952         }
7953
7954         *info_p = info;
7955         *count = numlines;
7956
7957         return WERR_OK;
7958 }
7959
7960 /****************************************************************
7961  _spoolss_EnumPorts
7962 ****************************************************************/
7963
7964 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7965                           struct spoolss_EnumPorts *r)
7966 {
7967         WERROR result;
7968
7969         /* that's an [in out] buffer */
7970
7971         if (!r->in.buffer && (r->in.offered != 0)) {
7972                 return WERR_INVALID_PARAM;
7973         }
7974
7975         DEBUG(4,("_spoolss_EnumPorts\n"));
7976
7977         *r->out.count = 0;
7978         *r->out.needed = 0;
7979         *r->out.info = NULL;
7980
7981         switch (r->in.level) {
7982         case 1:
7983                 result = enumports_level_1(p->mem_ctx, r->out.info,
7984                                            r->out.count);
7985                 break;
7986         case 2:
7987                 result = enumports_level_2(p->mem_ctx, r->out.info,
7988                                            r->out.count);
7989                 break;
7990         default:
7991                 return WERR_UNKNOWN_LEVEL;
7992         }
7993
7994         if (!W_ERROR_IS_OK(result)) {
7995                 return result;
7996         }
7997
7998         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7999                                                      spoolss_EnumPorts,
8000                                                      *r->out.info, r->in.level,
8001                                                      *r->out.count);
8002         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8003         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8004
8005         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8006 }
8007
8008 /****************************************************************************
8009 ****************************************************************************/
8010
8011 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8012                                            const char *server,
8013                                            struct spoolss_SetPrinterInfoCtr *info_ctr,
8014                                            struct spoolss_DeviceMode *devmode,
8015                                            struct security_descriptor *secdesc,
8016                                            struct spoolss_UserLevelCtr *user_ctr,
8017                                            struct policy_handle *handle)
8018 {
8019         struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8020         uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8021         int     snum;
8022         WERROR err = WERR_OK;
8023
8024         /* samba does not have a concept of local, non-shared printers yet, so
8025          * make sure we always setup sharename - gd */
8026         if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8027             (info2->printername != NULL && info2->printername[0] != '\0')) {
8028                 DEBUG(5, ("spoolss_addprinterex_level_2: "
8029                         "no sharename has been set, setting printername %s as sharename\n",
8030                         info2->printername));
8031                 info2->sharename = info2->printername;
8032         }
8033
8034         /* check to see if the printer already exists */
8035         if ((snum = print_queue_snum(info2->sharename)) != -1) {
8036                 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8037                         info2->sharename));
8038                 return WERR_PRINTER_ALREADY_EXISTS;
8039         }
8040
8041         if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8042                 if ((snum = print_queue_snum(info2->printername)) != -1) {
8043                         DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8044                                 info2->printername));
8045                         return WERR_PRINTER_ALREADY_EXISTS;
8046                 }
8047         }
8048
8049         /* validate printer info struct */
8050         if (!info2->printername || strlen(info2->printername) == 0) {
8051                 return WERR_INVALID_PRINTER_NAME;
8052         }
8053         if (!info2->portname || strlen(info2->portname) == 0) {
8054                 return WERR_UNKNOWN_PORT;
8055         }
8056         if (!info2->drivername || strlen(info2->drivername) == 0) {
8057                 return WERR_UNKNOWN_PRINTER_DRIVER;
8058         }
8059         if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8060                 return WERR_UNKNOWN_PRINTPROCESSOR;
8061         }
8062
8063         /* FIXME!!!  smbd should check to see if the driver is installed before
8064            trying to add a printer like this  --jerry */
8065
8066         if (*lp_addprinter_cmd(talloc_tos()) ) {
8067                 char *raddr;
8068
8069                 raddr = tsocket_address_inet_addr_string(p->remote_address,
8070                                                          p->mem_ctx);
8071                 if (raddr == NULL) {
8072                         return WERR_NOMEM;
8073                 }
8074
8075                 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8076                                        info2, raddr,
8077                                        p->msg_ctx) ) {
8078                         return WERR_ACCESS_DENIED;
8079                 }
8080         } else {
8081                 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8082                         "smb.conf parameter \"addprinter command\" is defined. This "
8083                         "parameter must exist for this call to succeed\n",
8084                         info2->sharename ));
8085         }
8086
8087         if ((snum = print_queue_snum(info2->sharename)) == -1) {
8088                 return WERR_ACCESS_DENIED;
8089         }
8090
8091         /* you must be a printer admin to add a new printer */
8092         if (!print_access_check(p->session_info,
8093                                 p->msg_ctx,
8094                                 snum,
8095                                 PRINTER_ACCESS_ADMINISTER)) {
8096                 return WERR_ACCESS_DENIED;
8097         }
8098
8099         /*
8100          * Do sanity check on the requested changes for Samba.
8101          */
8102
8103         if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8104                 return WERR_INVALID_PARAM;
8105         }
8106
8107         if (devmode == NULL) {
8108                 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8109         }
8110
8111         err = update_dsspooler(p->mem_ctx,
8112                                get_session_info_system(),
8113                                p->msg_ctx,
8114                                0,
8115                                info2,
8116                                NULL);
8117         if (!W_ERROR_IS_OK(err)) {
8118                 return err;
8119         }
8120
8121         err = winreg_update_printer_internal(p->mem_ctx,
8122                                     get_session_info_system(),
8123                                     p->msg_ctx,
8124                                     info2->sharename,
8125                                     info2_mask,
8126                                     info2,
8127                                     devmode,
8128                                     secdesc);
8129         if (!W_ERROR_IS_OK(err)) {
8130                 return err;
8131         }
8132
8133         err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8134         if (!W_ERROR_IS_OK(err)) {
8135                 /* Handle open failed - remove addition. */
8136                 ZERO_STRUCTP(handle);
8137                 return err;
8138         }
8139
8140         return WERR_OK;
8141 }
8142
8143 /****************************************************************
8144  _spoolss_AddPrinterEx
8145 ****************************************************************/
8146
8147 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8148                              struct spoolss_AddPrinterEx *r)
8149 {
8150         switch (r->in.info_ctr->level) {
8151         case 1:
8152                 /* we don't handle yet */
8153                 /* but I know what to do ... */
8154                 return WERR_UNKNOWN_LEVEL;
8155         case 2:
8156                 return spoolss_addprinterex_level_2(p, r->in.server,
8157                                                     r->in.info_ctr,
8158                                                     r->in.devmode_ctr->devmode,
8159                                                     r->in.secdesc_ctr->sd,
8160                                                     r->in.userlevel_ctr,
8161                                                     r->out.handle);
8162         default:
8163                 return WERR_UNKNOWN_LEVEL;
8164         }
8165 }
8166
8167 /****************************************************************
8168  _spoolss_AddPrinter
8169 ****************************************************************/
8170
8171 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8172                            struct spoolss_AddPrinter *r)
8173 {
8174         struct spoolss_AddPrinterEx a;
8175         struct spoolss_UserLevelCtr userlevel_ctr;
8176
8177         ZERO_STRUCT(userlevel_ctr);
8178
8179         userlevel_ctr.level = 1;
8180
8181         a.in.server             = r->in.server;
8182         a.in.info_ctr           = r->in.info_ctr;
8183         a.in.devmode_ctr        = r->in.devmode_ctr;
8184         a.in.secdesc_ctr        = r->in.secdesc_ctr;
8185         a.in.userlevel_ctr      = &userlevel_ctr;
8186         a.out.handle            = r->out.handle;
8187
8188         return _spoolss_AddPrinterEx(p, &a);
8189 }
8190
8191 /****************************************************************
8192  _spoolss_AddPrinterDriverEx
8193 ****************************************************************/
8194
8195 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8196                                    struct spoolss_AddPrinterDriverEx *r)
8197 {
8198         WERROR err = WERR_OK;
8199         const char *driver_name = NULL;
8200         uint32_t version;
8201         const char *fn;
8202
8203         switch (p->opnum) {
8204                 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8205                         fn = "_spoolss_AddPrinterDriver";
8206                         break;
8207                 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8208                         fn = "_spoolss_AddPrinterDriverEx";
8209                         break;
8210                 default:
8211                         return WERR_INVALID_PARAM;
8212         }
8213
8214         /*
8215          * we only support the semantics of AddPrinterDriver()
8216          * i.e. only copy files that are newer than existing ones
8217          */
8218
8219         if (r->in.flags == 0) {
8220                 return WERR_INVALID_PARAM;
8221         }
8222
8223         if (r->in.flags != APD_COPY_NEW_FILES) {
8224                 return WERR_ACCESS_DENIED;
8225         }
8226
8227         /* FIXME */
8228         if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8229                 /* Clever hack from Martin Zielinski <mz@seh.de>
8230                  * to allow downgrade from level 8 (Vista).
8231                  */
8232                 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8233                         r->in.info_ctr->level));
8234                 return WERR_UNKNOWN_LEVEL;
8235         }
8236
8237         DEBUG(5,("Cleaning driver's information\n"));
8238         err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8239         if (!W_ERROR_IS_OK(err))
8240                 goto done;
8241
8242         DEBUG(5,("Moving driver to final destination\n"));
8243         err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8244         if (!W_ERROR_IS_OK(err)) {
8245                 goto done;
8246         }
8247
8248         err = winreg_add_driver_internal(p->mem_ctx,
8249                                 get_session_info_system(),
8250                                 p->msg_ctx,
8251                                 r->in.info_ctr,
8252                                 &driver_name,
8253                                 &version);
8254         if (!W_ERROR_IS_OK(err)) {
8255                 goto done;
8256         }
8257
8258         /*
8259          * I think this is where he DrvUpgradePrinter() hook would be
8260          * be called in a driver's interface DLL on a Windows NT 4.0/2k
8261          * server.  Right now, we just need to send ourselves a message
8262          * to update each printer bound to this driver.   --jerry
8263          */
8264
8265         if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8266                 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8267                         fn, driver_name));
8268         }
8269
8270 done:
8271         return err;
8272 }
8273
8274 /****************************************************************
8275  _spoolss_AddPrinterDriver
8276 ****************************************************************/
8277
8278 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8279                                  struct spoolss_AddPrinterDriver *r)
8280 {
8281         struct spoolss_AddPrinterDriverEx a;
8282
8283         switch (r->in.info_ctr->level) {
8284         case 2:
8285         case 3:
8286         case 4:
8287         case 5:
8288                 break;
8289         default:
8290                 return WERR_UNKNOWN_LEVEL;
8291         }
8292
8293         a.in.servername         = r->in.servername;
8294         a.in.info_ctr           = r->in.info_ctr;
8295         a.in.flags              = APD_COPY_NEW_FILES;
8296
8297         return _spoolss_AddPrinterDriverEx(p, &a);
8298 }
8299
8300 /****************************************************************************
8301 ****************************************************************************/
8302
8303 struct _spoolss_paths {
8304         int type;
8305         const char *share;
8306         const char *dir;
8307 };
8308
8309 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8310
8311 static const struct _spoolss_paths spoolss_paths[]= {
8312         { SPOOLSS_DRIVER_PATH,          "print$",       "DRIVERS" },
8313         { SPOOLSS_PRTPROCS_PATH,        "prnproc$",     "PRTPROCS" }
8314 };
8315
8316 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8317                                           const char *servername,
8318                                           const char *environment,
8319                                           int component,
8320                                           char **path)
8321 {
8322         const char *pservername = NULL;
8323         const char *long_archi;
8324         const char *short_archi;
8325
8326         *path = NULL;
8327
8328         /* environment may be empty */
8329         if (environment && strlen(environment)) {
8330                 long_archi = environment;
8331         } else {
8332                 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8333                                                   "spoolss", "architecture",
8334                                                   SPOOLSS_ARCHITECTURE_NT_X86);
8335         }
8336
8337         /* servername may be empty */
8338         if (servername && strlen(servername)) {
8339                 pservername = canon_servername(servername);
8340
8341                 if (!is_myname_or_ipaddr(pservername)) {
8342                         return WERR_INVALID_PARAM;
8343                 }
8344         }
8345
8346         if (!(short_archi = get_short_archi(long_archi))) {
8347                 return WERR_INVALID_ENVIRONMENT;
8348         }
8349
8350         switch (component) {
8351         case SPOOLSS_PRTPROCS_PATH:
8352         case SPOOLSS_DRIVER_PATH:
8353                 if (pservername) {
8354                         *path = talloc_asprintf(mem_ctx,
8355                                         "\\\\%s\\%s\\%s",
8356                                         pservername,
8357                                         spoolss_paths[component].share,
8358                                         short_archi);
8359                 } else {
8360                         *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8361                                         SPOOLSS_DEFAULT_SERVER_PATH,
8362                                         spoolss_paths[component].dir,
8363                                         short_archi);
8364                 }
8365                 break;
8366         default:
8367                 return WERR_INVALID_PARAM;
8368         }
8369
8370         if (!*path) {
8371                 return WERR_NOMEM;
8372         }
8373
8374         return WERR_OK;
8375 }
8376
8377 /****************************************************************************
8378 ****************************************************************************/
8379
8380 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8381                                           const char *servername,
8382                                           const char *environment,
8383                                           struct spoolss_DriverDirectoryInfo1 *r)
8384 {
8385         WERROR werr;
8386         char *path = NULL;
8387
8388         werr = compose_spoolss_server_path(mem_ctx,
8389                                            servername,
8390                                            environment,
8391                                            SPOOLSS_DRIVER_PATH,
8392                                            &path);
8393         if (!W_ERROR_IS_OK(werr)) {
8394                 return werr;
8395         }
8396
8397         DEBUG(4,("printer driver directory: [%s]\n", path));
8398
8399         r->directory_name = path;
8400
8401         return WERR_OK;
8402 }
8403
8404 /****************************************************************
8405  _spoolss_GetPrinterDriverDirectory
8406 ****************************************************************/
8407
8408 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8409                                           struct spoolss_GetPrinterDriverDirectory *r)
8410 {
8411         WERROR werror;
8412
8413         /* that's an [in out] buffer */
8414
8415         if (!r->in.buffer && (r->in.offered != 0)) {
8416                 return WERR_INVALID_PARAM;
8417         }
8418
8419         DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8420                 r->in.level));
8421
8422         *r->out.needed = 0;
8423
8424         /* r->in.level is ignored */
8425
8426         werror = getprinterdriverdir_level_1(p->mem_ctx,
8427                                              r->in.server,
8428                                              r->in.environment,
8429                                              &r->out.info->info1);
8430         if (!W_ERROR_IS_OK(werror)) {
8431                 TALLOC_FREE(r->out.info);
8432                 return werror;
8433         }
8434
8435         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8436                                                r->out.info, r->in.level);
8437         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8438
8439         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8440 }
8441
8442 /****************************************************************
8443  _spoolss_EnumPrinterData
8444 ****************************************************************/
8445
8446 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8447                                 struct spoolss_EnumPrinterData *r)
8448 {
8449         WERROR result;
8450         struct spoolss_EnumPrinterDataEx r2;
8451         uint32_t count;
8452         struct spoolss_PrinterEnumValues *info, *val = NULL;
8453         uint32_t needed;
8454
8455         r2.in.handle    = r->in.handle;
8456         r2.in.key_name  = "PrinterDriverData";
8457         r2.in.offered   = 0;
8458         r2.out.count    = &count;
8459         r2.out.info     = &info;
8460         r2.out.needed   = &needed;
8461
8462         result = _spoolss_EnumPrinterDataEx(p, &r2);
8463         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8464                 r2.in.offered = needed;
8465                 result = _spoolss_EnumPrinterDataEx(p, &r2);
8466         }
8467         if (!W_ERROR_IS_OK(result)) {
8468                 return result;
8469         }
8470
8471         /*
8472          * The NT machine wants to know the biggest size of value and data
8473          *
8474          * cf: MSDN EnumPrinterData remark section
8475          */
8476
8477         if (!r->in.value_offered && !r->in.data_offered) {
8478                 uint32_t biggest_valuesize = 0;
8479                 uint32_t biggest_datasize = 0;
8480                 int i, name_length;
8481
8482                 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8483
8484                 for (i=0; i<count; i++) {
8485
8486                         name_length = strlen(info[i].value_name);
8487                         if (strlen(info[i].value_name) > biggest_valuesize) {
8488                                 biggest_valuesize = name_length;
8489                         }
8490
8491                         if (info[i].data_length > biggest_datasize) {
8492                                 biggest_datasize = info[i].data_length;
8493                         }
8494
8495                         DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8496                                 biggest_datasize));
8497                 }
8498
8499                 /* the value is an UNICODE string but real_value_size is the length
8500                    in bytes including the trailing 0 */
8501
8502                 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8503                 *r->out.data_needed  = biggest_datasize;
8504
8505                 DEBUG(6,("final values: [%d], [%d]\n",
8506                         *r->out.value_needed, *r->out.data_needed));
8507
8508                 return WERR_OK;
8509         }
8510
8511         if (r->in.enum_index < count) {
8512                 val = &info[r->in.enum_index];
8513         }
8514
8515         if (val == NULL) {
8516                 /* out_value should default to "" or else NT4 has
8517                    problems unmarshalling the response */
8518
8519                 if (r->in.value_offered) {
8520                         *r->out.value_needed = 1;
8521                         r->out.value_name = talloc_strdup(r, "");
8522                         if (!r->out.value_name) {
8523                                 return WERR_NOMEM;
8524                         }
8525                 } else {
8526                         r->out.value_name = NULL;
8527                         *r->out.value_needed = 0;
8528                 }
8529
8530                 /* the data is counted in bytes */
8531
8532                 *r->out.data_needed = r->in.data_offered;
8533
8534                 result = WERR_NO_MORE_ITEMS;
8535         } else {
8536                 /*
8537                  * the value is:
8538                  * - counted in bytes in the request
8539                  * - counted in UNICODE chars in the max reply
8540                  * - counted in bytes in the real size
8541                  *
8542                  * take a pause *before* coding not *during* coding
8543                  */
8544
8545                 /* name */
8546                 if (r->in.value_offered) {
8547                         r->out.value_name = talloc_strdup(r, val->value_name);
8548                         if (!r->out.value_name) {
8549                                 return WERR_NOMEM;
8550                         }
8551                         *r->out.value_needed = val->value_name_len;
8552                 } else {
8553                         r->out.value_name = NULL;
8554                         *r->out.value_needed = 0;
8555                 }
8556
8557                 /* type */
8558
8559                 *r->out.type = val->type;
8560
8561                 /* data - counted in bytes */
8562
8563                 /*
8564                  * See the section "Dynamically Typed Query Parameters"
8565                  * in MS-RPRN.
8566                  */
8567
8568                 if (r->out.data && val->data && val->data->data &&
8569                                 val->data_length && r->in.data_offered) {
8570                         memcpy(r->out.data, val->data->data,
8571                                 MIN(val->data_length,r->in.data_offered));
8572                 }
8573
8574                 *r->out.data_needed = val->data_length;
8575
8576                 result = WERR_OK;
8577         }
8578
8579         return result;
8580 }
8581
8582 /****************************************************************
8583  _spoolss_SetPrinterData
8584 ****************************************************************/
8585
8586 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8587                                struct spoolss_SetPrinterData *r)
8588 {
8589         struct spoolss_SetPrinterDataEx r2;
8590
8591         r2.in.handle            = r->in.handle;
8592         r2.in.key_name          = "PrinterDriverData";
8593         r2.in.value_name        = r->in.value_name;
8594         r2.in.type              = r->in.type;
8595         r2.in.data              = r->in.data;
8596         r2.in.offered           = r->in.offered;
8597
8598         return _spoolss_SetPrinterDataEx(p, &r2);
8599 }
8600
8601 /****************************************************************
8602  _spoolss_ResetPrinter
8603 ****************************************************************/
8604
8605 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8606                              struct spoolss_ResetPrinter *r)
8607 {
8608         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8609         int             snum;
8610
8611         DEBUG(5,("_spoolss_ResetPrinter\n"));
8612
8613         /*
8614          * All we do is to check to see if the handle and queue is valid.
8615          * This call really doesn't mean anything to us because we only
8616          * support RAW printing.   --jerry
8617          */
8618
8619         if (!Printer) {
8620                 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8621                         OUR_HANDLE(r->in.handle)));
8622                 return WERR_BADFID;
8623         }
8624
8625         if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8626                 return WERR_BADFID;
8627
8628
8629         /* blindly return success */
8630         return WERR_OK;
8631 }
8632
8633 /****************************************************************
8634  _spoolss_DeletePrinterData
8635 ****************************************************************/
8636
8637 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8638                                   struct spoolss_DeletePrinterData *r)
8639 {
8640         struct spoolss_DeletePrinterDataEx r2;
8641
8642         r2.in.handle            = r->in.handle;
8643         r2.in.key_name          = "PrinterDriverData";
8644         r2.in.value_name        = r->in.value_name;
8645
8646         return _spoolss_DeletePrinterDataEx(p, &r2);
8647 }
8648
8649 /****************************************************************
8650  _spoolss_AddForm
8651 ****************************************************************/
8652
8653 WERROR _spoolss_AddForm(struct pipes_struct *p,
8654                         struct spoolss_AddForm *r)
8655 {
8656         struct spoolss_AddFormInfo1 *form;
8657         int snum = -1;
8658         WERROR status = WERR_OK;
8659         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8660         struct dcerpc_binding_handle *b;
8661         TALLOC_CTX *tmp_ctx = NULL;
8662
8663         DEBUG(5,("_spoolss_AddForm\n"));
8664
8665         if (!Printer) {
8666                 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8667                         OUR_HANDLE(r->in.handle)));
8668                 return WERR_BADFID;
8669         }
8670
8671         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8672            and not a printer admin, then fail */
8673
8674         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8675             !security_token_has_privilege(p->session_info->security_token,
8676                                           SEC_PRIV_PRINT_OPERATOR)) {
8677                 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8678                 return WERR_ACCESS_DENIED;
8679         }
8680
8681         if (r->in.info_ctr->level != 1) {
8682                 return WERR_INVALID_LEVEL;
8683         }
8684
8685         form = r->in.info_ctr->info.info1;
8686         if (!form) {
8687                 return WERR_INVALID_PARAM;
8688         }
8689
8690         switch (form->flags) {
8691         case SPOOLSS_FORM_USER:
8692         case SPOOLSS_FORM_BUILTIN:
8693         case SPOOLSS_FORM_PRINTER:
8694                 break;
8695         default:
8696                 return WERR_INVALID_PARAM;
8697         }
8698
8699         tmp_ctx = talloc_new(p->mem_ctx);
8700         if (!tmp_ctx) {
8701                 return WERR_NOMEM;
8702         }
8703
8704         status = winreg_printer_binding_handle(tmp_ctx,
8705                                                get_session_info_system(),
8706                                                p->msg_ctx,
8707                                                &b);
8708         if (!W_ERROR_IS_OK(status)) {
8709                 goto done;
8710         }
8711
8712         status = winreg_printer_addform1(tmp_ctx, b, form);
8713         if (!W_ERROR_IS_OK(status)) {
8714                 goto done;
8715         }
8716
8717         /*
8718          * ChangeID must always be set if this is a printer
8719          */
8720         if (Printer->printer_type == SPLHND_PRINTER) {
8721                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8722                         status = WERR_BADFID;
8723                         goto done;
8724                 }
8725
8726                 status = winreg_printer_update_changeid(tmp_ctx, b,
8727                                                         lp_const_servicename(snum));
8728         }
8729
8730 done:
8731         talloc_free(tmp_ctx);
8732         return status;
8733 }
8734
8735 /****************************************************************
8736  _spoolss_DeleteForm
8737 ****************************************************************/
8738
8739 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8740                            struct spoolss_DeleteForm *r)
8741 {
8742         const char *form_name = r->in.form_name;
8743         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8744         int snum = -1;
8745         WERROR status = WERR_OK;
8746         struct dcerpc_binding_handle *b;
8747         TALLOC_CTX *tmp_ctx = NULL;
8748
8749         DEBUG(5,("_spoolss_DeleteForm\n"));
8750
8751         if (!Printer) {
8752                 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8753                         OUR_HANDLE(r->in.handle)));
8754                 return WERR_BADFID;
8755         }
8756
8757         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8758             !security_token_has_privilege(p->session_info->security_token,
8759                                           SEC_PRIV_PRINT_OPERATOR)) {
8760                 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8761                 return WERR_ACCESS_DENIED;
8762         }
8763
8764         tmp_ctx = talloc_new(p->mem_ctx);
8765         if (!tmp_ctx) {
8766                 return WERR_NOMEM;
8767         }
8768
8769         status = winreg_printer_binding_handle(tmp_ctx,
8770                                                get_session_info_system(),
8771                                                p->msg_ctx,
8772                                                &b);
8773         if (!W_ERROR_IS_OK(status)) {
8774                 goto done;
8775         }
8776
8777         status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8778         if (!W_ERROR_IS_OK(status)) {
8779                 goto done;
8780         }
8781
8782         /*
8783          * ChangeID must always be set if this is a printer
8784          */
8785         if (Printer->printer_type == SPLHND_PRINTER) {
8786                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8787                         status = WERR_BADFID;
8788                         goto done;
8789                 }
8790
8791                 status = winreg_printer_update_changeid(tmp_ctx, b,
8792                                                         lp_const_servicename(snum));
8793         }
8794
8795 done:
8796         talloc_free(tmp_ctx);
8797         return status;
8798 }
8799
8800 /****************************************************************
8801  _spoolss_SetForm
8802 ****************************************************************/
8803
8804 WERROR _spoolss_SetForm(struct pipes_struct *p,
8805                         struct spoolss_SetForm *r)
8806 {
8807         struct spoolss_AddFormInfo1 *form;
8808         const char *form_name = r->in.form_name;
8809         int snum = -1;
8810         WERROR status = WERR_OK;
8811         struct dcerpc_binding_handle *b;
8812         TALLOC_CTX *tmp_ctx = NULL;
8813
8814         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8815
8816         DEBUG(5,("_spoolss_SetForm\n"));
8817
8818         if (!Printer) {
8819                 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8820                         OUR_HANDLE(r->in.handle)));
8821                 return WERR_BADFID;
8822         }
8823
8824         /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8825            and not a printer admin, then fail */
8826
8827         if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8828              !security_token_has_privilege(p->session_info->security_token,
8829                                            SEC_PRIV_PRINT_OPERATOR)) {
8830                 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8831                 return WERR_ACCESS_DENIED;
8832         }
8833
8834         if (r->in.info_ctr->level != 1) {
8835                 return WERR_INVALID_LEVEL;
8836         }
8837
8838         form = r->in.info_ctr->info.info1;
8839         if (!form) {
8840                 return WERR_INVALID_PARAM;
8841         }
8842
8843         tmp_ctx = talloc_new(p->mem_ctx);
8844         if (!tmp_ctx) {
8845                 return WERR_NOMEM;
8846         }
8847
8848         status = winreg_printer_binding_handle(tmp_ctx,
8849                                                get_session_info_system(),
8850                                                p->msg_ctx,
8851                                                &b);
8852         if (!W_ERROR_IS_OK(status)) {
8853                 goto done;
8854         }
8855
8856         status = winreg_printer_setform1(tmp_ctx, b,
8857                                          form_name,
8858                                          form);
8859         if (!W_ERROR_IS_OK(status)) {
8860                 goto done;
8861         }
8862
8863         /*
8864          * ChangeID must always be set if this is a printer
8865          */
8866         if (Printer->printer_type == SPLHND_PRINTER) {
8867                 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8868                         status = WERR_BADFID;
8869                         goto done;
8870                 }
8871
8872                 status = winreg_printer_update_changeid(tmp_ctx, b,
8873                                                         lp_const_servicename(snum));
8874         }
8875
8876 done:
8877         talloc_free(tmp_ctx);
8878         return status;
8879 }
8880
8881 /****************************************************************************
8882  fill_print_processor1
8883 ****************************************************************************/
8884
8885 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8886                                     struct spoolss_PrintProcessorInfo1 *r,
8887                                     const char *print_processor_name)
8888 {
8889         r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8890         W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8891
8892         return WERR_OK;
8893 }
8894
8895 /****************************************************************************
8896  enumprintprocessors level 1.
8897 ****************************************************************************/
8898
8899 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8900                                           union spoolss_PrintProcessorInfo **info_p,
8901                                           uint32_t *count)
8902 {
8903         union spoolss_PrintProcessorInfo *info;
8904         WERROR result;
8905
8906         info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8907         W_ERROR_HAVE_NO_MEMORY(info);
8908
8909         *count = 1;
8910
8911         result = fill_print_processor1(info, &info[0].info1, "winprint");
8912         if (!W_ERROR_IS_OK(result)) {
8913                 goto out;
8914         }
8915
8916  out:
8917         if (!W_ERROR_IS_OK(result)) {
8918                 TALLOC_FREE(info);
8919                 *count = 0;
8920                 return result;
8921         }
8922
8923         *info_p = info;
8924
8925         return WERR_OK;
8926 }
8927
8928 /****************************************************************
8929  _spoolss_EnumPrintProcessors
8930 ****************************************************************/
8931
8932 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8933                                     struct spoolss_EnumPrintProcessors *r)
8934 {
8935         WERROR result;
8936
8937         /* that's an [in out] buffer */
8938
8939         if (!r->in.buffer && (r->in.offered != 0)) {
8940                 return WERR_INVALID_PARAM;
8941         }
8942
8943         DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8944
8945         /*
8946          * Enumerate the print processors ...
8947          *
8948          * Just reply with "winprint", to keep NT happy
8949          * and I can use my nice printer checker.
8950          */
8951
8952         *r->out.count = 0;
8953         *r->out.needed = 0;
8954         *r->out.info = NULL;
8955
8956         if (!get_short_archi(r->in.environment)) {
8957                 return WERR_INVALID_ENVIRONMENT;
8958         }
8959
8960         switch (r->in.level) {
8961         case 1:
8962                 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8963                                                      r->out.count);
8964                 break;
8965         default:
8966                 return WERR_UNKNOWN_LEVEL;
8967         }
8968
8969         if (!W_ERROR_IS_OK(result)) {
8970                 return result;
8971         }
8972
8973         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8974                                                      spoolss_EnumPrintProcessors,
8975                                                      *r->out.info, r->in.level,
8976                                                      *r->out.count);
8977         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8978         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8979
8980         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8981 }
8982
8983 /****************************************************************************
8984  fill_printprocdatatype1
8985 ****************************************************************************/
8986
8987 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8988                                       struct spoolss_PrintProcDataTypesInfo1 *r,
8989                                       const char *name_array)
8990 {
8991         r->name_array = talloc_strdup(mem_ctx, name_array);
8992         W_ERROR_HAVE_NO_MEMORY(r->name_array);
8993
8994         return WERR_OK;
8995 }
8996
8997 /****************************************************************************
8998  enumprintprocdatatypes level 1.
8999 ****************************************************************************/
9000
9001 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9002                                              union spoolss_PrintProcDataTypesInfo **info_p,
9003                                              uint32_t *count)
9004 {
9005         WERROR result;
9006         union spoolss_PrintProcDataTypesInfo *info;
9007
9008         info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9009         W_ERROR_HAVE_NO_MEMORY(info);
9010
9011         *count = 1;
9012
9013         result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9014         if (!W_ERROR_IS_OK(result)) {
9015                 goto out;
9016         }
9017
9018  out:
9019         if (!W_ERROR_IS_OK(result)) {
9020                 TALLOC_FREE(info);
9021                 *count = 0;
9022                 return result;
9023         }
9024
9025         *info_p = info;
9026
9027         return WERR_OK;
9028 }
9029
9030 /****************************************************************
9031  _spoolss_EnumPrintProcDataTypes
9032 ****************************************************************/
9033
9034 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9035                                        struct spoolss_EnumPrintProcDataTypes *r)
9036 {
9037         WERROR result;
9038
9039         /* that's an [in out] buffer */
9040
9041         if (!r->in.buffer && (r->in.offered != 0)) {
9042                 return WERR_INVALID_PARAM;
9043         }
9044
9045         DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9046
9047         *r->out.count = 0;
9048         *r->out.needed = 0;
9049         *r->out.info = NULL;
9050
9051         if (r->in.print_processor_name == NULL ||
9052             !strequal(r->in.print_processor_name, "winprint")) {
9053                 return WERR_UNKNOWN_PRINTPROCESSOR;
9054         }
9055
9056         switch (r->in.level) {
9057         case 1:
9058                 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9059                                                         r->out.count);
9060                 break;
9061         default:
9062                 return WERR_UNKNOWN_LEVEL;
9063         }
9064
9065         if (!W_ERROR_IS_OK(result)) {
9066                 return result;
9067         }
9068
9069         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9070                                                      spoolss_EnumPrintProcDataTypes,
9071                                                      *r->out.info, r->in.level,
9072                                                      *r->out.count);
9073         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9074         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9075
9076         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9077 }
9078
9079 /****************************************************************************
9080  fill_monitor_1
9081 ****************************************************************************/
9082
9083 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9084                              struct spoolss_MonitorInfo1 *r,
9085                              const char *monitor_name)
9086 {
9087         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9088         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9089
9090         return WERR_OK;
9091 }
9092
9093 /****************************************************************************
9094  fill_monitor_2
9095 ****************************************************************************/
9096
9097 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9098                              struct spoolss_MonitorInfo2 *r,
9099                              const char *monitor_name,
9100                              const char *environment,
9101                              const char *dll_name)
9102 {
9103         r->monitor_name                 = talloc_strdup(mem_ctx, monitor_name);
9104         W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9105         r->environment                  = talloc_strdup(mem_ctx, environment);
9106         W_ERROR_HAVE_NO_MEMORY(r->environment);
9107         r->dll_name                     = talloc_strdup(mem_ctx, dll_name);
9108         W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9109
9110         return WERR_OK;
9111 }
9112
9113 /****************************************************************************
9114  enumprintmonitors level 1.
9115 ****************************************************************************/
9116
9117 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9118                                         union spoolss_MonitorInfo **info_p,
9119                                         uint32_t *count)
9120 {
9121         union spoolss_MonitorInfo *info;
9122         WERROR result = WERR_OK;
9123
9124         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9125         W_ERROR_HAVE_NO_MEMORY(info);
9126
9127         *count = 2;
9128
9129         result = fill_monitor_1(info, &info[0].info1,
9130                                 SPL_LOCAL_PORT);
9131         if (!W_ERROR_IS_OK(result)) {
9132                 goto out;
9133         }
9134
9135         result = fill_monitor_1(info, &info[1].info1,
9136                                 SPL_TCPIP_PORT);
9137         if (!W_ERROR_IS_OK(result)) {
9138                 goto out;
9139         }
9140
9141 out:
9142         if (!W_ERROR_IS_OK(result)) {
9143                 TALLOC_FREE(info);
9144                 *count = 0;
9145                 return result;
9146         }
9147
9148         *info_p = info;
9149
9150         return WERR_OK;
9151 }
9152
9153 /****************************************************************************
9154  enumprintmonitors level 2.
9155 ****************************************************************************/
9156
9157 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9158                                         union spoolss_MonitorInfo **info_p,
9159                                         uint32_t *count)
9160 {
9161         union spoolss_MonitorInfo *info;
9162         WERROR result = WERR_OK;
9163
9164         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9165         W_ERROR_HAVE_NO_MEMORY(info);
9166
9167         *count = 2;
9168
9169         result = fill_monitor_2(info, &info[0].info2,
9170                                 SPL_LOCAL_PORT,
9171                                 "Windows NT X86", /* FIXME */
9172                                 "localmon.dll");
9173         if (!W_ERROR_IS_OK(result)) {
9174                 goto out;
9175         }
9176
9177         result = fill_monitor_2(info, &info[1].info2,
9178                                 SPL_TCPIP_PORT,
9179                                 "Windows NT X86", /* FIXME */
9180                                 "tcpmon.dll");
9181         if (!W_ERROR_IS_OK(result)) {
9182                 goto out;
9183         }
9184
9185 out:
9186         if (!W_ERROR_IS_OK(result)) {
9187                 TALLOC_FREE(info);
9188                 *count = 0;
9189                 return result;
9190         }
9191
9192         *info_p = info;
9193
9194         return WERR_OK;
9195 }
9196
9197 /****************************************************************
9198  _spoolss_EnumMonitors
9199 ****************************************************************/
9200
9201 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9202                              struct spoolss_EnumMonitors *r)
9203 {
9204         WERROR result;
9205
9206         /* that's an [in out] buffer */
9207
9208         if (!r->in.buffer && (r->in.offered != 0)) {
9209                 return WERR_INVALID_PARAM;
9210         }
9211
9212         DEBUG(5,("_spoolss_EnumMonitors\n"));
9213
9214         /*
9215          * Enumerate the print monitors ...
9216          *
9217          * Just reply with "Local Port", to keep NT happy
9218          * and I can use my nice printer checker.
9219          */
9220
9221         *r->out.count = 0;
9222         *r->out.needed = 0;
9223         *r->out.info = NULL;
9224
9225         switch (r->in.level) {
9226         case 1:
9227                 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9228                                                    r->out.count);
9229                 break;
9230         case 2:
9231                 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9232                                                    r->out.count);
9233                 break;
9234         default:
9235                 return WERR_UNKNOWN_LEVEL;
9236         }
9237
9238         if (!W_ERROR_IS_OK(result)) {
9239                 return result;
9240         }
9241
9242         *r->out.needed  = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9243                                                      spoolss_EnumMonitors,
9244                                                      *r->out.info, r->in.level,
9245                                                      *r->out.count);
9246         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9247         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9248
9249         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9250 }
9251
9252 /****************************************************************************
9253 ****************************************************************************/
9254
9255 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9256                              const print_queue_struct *queue,
9257                              int count, int snum,
9258                              struct spoolss_PrinterInfo2 *pinfo2,
9259                              uint32_t jobid,
9260                              struct spoolss_JobInfo1 *r)
9261 {
9262         int i = 0;
9263         bool found = false;
9264
9265         for (i=0; i<count; i++) {
9266                 if (queue[i].sysjob == (int)jobid) {
9267                         found = true;
9268                         break;
9269                 }
9270         }
9271
9272         if (found == false) {
9273                 /* NT treats not found as bad param... yet another bad choice */
9274                 return WERR_INVALID_PARAM;
9275         }
9276
9277         return fill_job_info1(mem_ctx,
9278                               r,
9279                               &queue[i],
9280                               i,
9281                               snum,
9282                               pinfo2);
9283 }
9284
9285 /****************************************************************************
9286 ****************************************************************************/
9287
9288 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9289                              const print_queue_struct *queue,
9290                              int count, int snum,
9291                              struct spoolss_PrinterInfo2 *pinfo2,
9292                              uint32_t jobid,
9293                              struct spoolss_JobInfo2 *r)
9294 {
9295         int i = 0;
9296         bool found = false;
9297         struct spoolss_DeviceMode *devmode;
9298         WERROR result;
9299
9300         for (i=0; i<count; i++) {
9301                 if (queue[i].sysjob == (int)jobid) {
9302                         found = true;
9303                         break;
9304                 }
9305         }
9306
9307         if (found == false) {
9308                 /* NT treats not found as bad param... yet another bad
9309                    choice */
9310                 return WERR_INVALID_PARAM;
9311         }
9312
9313         /*
9314          * if the print job does not have a DEVMODE associated with it,
9315          * just use the one for the printer. A NULL devicemode is not
9316          *  a failure condition
9317          */
9318
9319         devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9320         if (!devmode) {
9321                 result = spoolss_create_default_devmode(mem_ctx,
9322                                                 pinfo2->printername,
9323                                                 &devmode);
9324                 if (!W_ERROR_IS_OK(result)) {
9325                         DEBUG(3, ("Can't proceed w/o a devmode!"));
9326                         return result;
9327                 }
9328         }
9329
9330         return fill_job_info2(mem_ctx,
9331                               r,
9332                               &queue[i],
9333                               i,
9334                               snum,
9335                               pinfo2,
9336                               devmode);
9337 }
9338
9339 /****************************************************************
9340  _spoolss_GetJob
9341 ****************************************************************/
9342
9343 WERROR _spoolss_GetJob(struct pipes_struct *p,
9344                        struct spoolss_GetJob *r)
9345 {
9346         WERROR result = WERR_OK;
9347         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9348         int snum;
9349         int count;
9350         print_queue_struct      *queue = NULL;
9351         print_status_struct prt_status;
9352
9353         /* that's an [in out] buffer */
9354
9355         if (!r->in.buffer && (r->in.offered != 0)) {
9356                 return WERR_INVALID_PARAM;
9357         }
9358
9359         DEBUG(5,("_spoolss_GetJob\n"));
9360
9361         *r->out.needed = 0;
9362
9363         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9364                 return WERR_BADFID;
9365         }
9366
9367         result = winreg_get_printer_internal(p->mem_ctx,
9368                                     get_session_info_system(),
9369                                     p->msg_ctx,
9370                                     lp_const_servicename(snum),
9371                                     &pinfo2);
9372         if (!W_ERROR_IS_OK(result)) {
9373                 return result;
9374         }
9375
9376         count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9377
9378         DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9379                      count, prt_status.status, prt_status.message));
9380
9381         switch (r->in.level) {
9382         case 1:
9383                 result = getjob_level_1(p->mem_ctx,
9384                                         queue, count, snum, pinfo2,
9385                                         r->in.job_id, &r->out.info->info1);
9386                 break;
9387         case 2:
9388                 result = getjob_level_2(p->mem_ctx,
9389                                         queue, count, snum, pinfo2,
9390                                         r->in.job_id, &r->out.info->info2);
9391                 break;
9392         default:
9393                 result = WERR_UNKNOWN_LEVEL;
9394                 break;
9395         }
9396
9397         SAFE_FREE(queue);
9398         TALLOC_FREE(pinfo2);
9399
9400         if (!W_ERROR_IS_OK(result)) {
9401                 TALLOC_FREE(r->out.info);
9402                 return result;
9403         }
9404
9405         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9406                                                                                    r->in.level);
9407         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9408
9409         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9410 }
9411
9412 /****************************************************************
9413  _spoolss_GetPrinterDataEx
9414 ****************************************************************/
9415
9416 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9417                                  struct spoolss_GetPrinterDataEx *r)
9418 {
9419
9420         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9421         const char *printer;
9422         int                     snum = 0;
9423         WERROR result = WERR_OK;
9424         DATA_BLOB blob;
9425         enum winreg_Type val_type = REG_NONE;
9426         uint8_t *val_data = NULL;
9427         uint32_t val_size = 0;
9428         struct dcerpc_binding_handle *b;
9429         TALLOC_CTX *tmp_ctx;
9430
9431         DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9432
9433         DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9434                 r->in.key_name, r->in.value_name));
9435
9436         /* in case of problem, return some default values */
9437
9438         *r->out.needed  = 0;
9439         *r->out.type    = REG_NONE;
9440
9441         tmp_ctx = talloc_new(p->mem_ctx);
9442         if (!tmp_ctx) {
9443                 return WERR_NOMEM;
9444         }
9445
9446         if (!Printer) {
9447                 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9448                         OUR_HANDLE(r->in.handle)));
9449                 result = WERR_BADFID;
9450                 goto done;
9451         }
9452
9453         /* check to see if the keyname is valid */
9454         if (!strlen(r->in.key_name)) {
9455                 result = WERR_INVALID_PARAM;
9456                 goto done;
9457         }
9458
9459         /* Is the handle to a printer or to the server? */
9460
9461         if (Printer->printer_type == SPLHND_SERVER) {
9462
9463                 union spoolss_PrinterData data;
9464
9465                 result = getprinterdata_printer_server(tmp_ctx,
9466                                                        r->in.value_name,
9467                                                        r->out.type,
9468                                                        &data);
9469                 if (!W_ERROR_IS_OK(result)) {
9470                         goto done;
9471                 }
9472
9473                 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9474                                                   *r->out.type, &data);
9475                 if (!W_ERROR_IS_OK(result)) {
9476                         goto done;
9477                 }
9478
9479                 *r->out.needed = blob.length;
9480
9481                 if (r->in.offered >= *r->out.needed) {
9482                         memcpy(r->out.data, blob.data, blob.length);
9483                 }
9484
9485                 result = WERR_OK;
9486                 goto done;
9487         }
9488
9489         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9490                 result = WERR_BADFID;
9491                 goto done;
9492         }
9493         printer = lp_const_servicename(snum);
9494
9495         result = winreg_printer_binding_handle(tmp_ctx,
9496                                                get_session_info_system(),
9497                                                p->msg_ctx,
9498                                                &b);
9499         if (!W_ERROR_IS_OK(result)) {
9500                 goto done;
9501         }
9502
9503         /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9504         if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9505             strequal(r->in.value_name, "ChangeId")) {
9506                 *r->out.type = REG_DWORD;
9507                 *r->out.needed = 4;
9508                 if (r->in.offered >= *r->out.needed) {
9509                         uint32_t changeid = 0;
9510
9511                         result = winreg_printer_get_changeid(tmp_ctx, b,
9512                                                              printer,
9513                                                              &changeid);
9514                         if (!W_ERROR_IS_OK(result)) {
9515                                 goto done;
9516                         }
9517
9518                         SIVAL(r->out.data, 0, changeid);
9519                         result = WERR_OK;
9520                 }
9521                 goto done;
9522         }
9523
9524         result = winreg_get_printer_dataex(tmp_ctx, b,
9525                                            printer,
9526                                            r->in.key_name,
9527                                            r->in.value_name,
9528                                            &val_type,
9529                                            &val_data,
9530                                            &val_size);
9531         if (!W_ERROR_IS_OK(result)) {
9532                 goto done;
9533         }
9534
9535         *r->out.needed = val_size;
9536         *r->out.type = val_type;
9537
9538         if (r->in.offered >= *r->out.needed) {
9539                 memcpy(r->out.data, val_data, val_size);
9540         }
9541
9542 done:
9543         /* NOTE: do not replace type when returning WERR_MORE_DATA */
9544
9545         if (W_ERROR_IS_OK(result)) {
9546                 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9547         }
9548
9549         talloc_free(tmp_ctx);
9550         return result;
9551 }
9552
9553 /****************************************************************
9554  _spoolss_SetPrinterDataEx
9555 ****************************************************************/
9556
9557 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9558                                  struct spoolss_SetPrinterDataEx *r)
9559 {
9560         struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9561         int                     snum = 0;
9562         WERROR                  result = WERR_OK;
9563         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9564         char                    *oid_string;
9565         struct dcerpc_binding_handle *b;
9566         TALLOC_CTX *tmp_ctx;
9567
9568         DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9569
9570         /* From MSDN documentation of SetPrinterDataEx: pass request to
9571            SetPrinterData if key is "PrinterDriverData" */
9572
9573         if (!Printer) {
9574                 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9575                         OUR_HANDLE(r->in.handle)));
9576                 return WERR_BADFID;
9577         }
9578
9579         if (Printer->printer_type == SPLHND_SERVER) {
9580                 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9581                         "Not implemented for server handles yet\n"));
9582                 return WERR_INVALID_PARAM;
9583         }
9584
9585         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9586                 return WERR_BADFID;
9587         }
9588
9589         /*
9590          * Access check : NT returns "access denied" if you make a
9591          * SetPrinterData call without the necessary privildge.
9592          * we were originally returning OK if nothing changed
9593          * which made Win2k issue **a lot** of SetPrinterData
9594          * when connecting to a printer  --jerry
9595          */
9596
9597         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9598                 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9599                         "change denied by handle access permissions\n"));
9600                 return WERR_ACCESS_DENIED;
9601         }
9602
9603         tmp_ctx = talloc_new(p->mem_ctx);
9604         if (!tmp_ctx) {
9605                 return WERR_NOMEM;
9606         }
9607
9608         result = winreg_printer_binding_handle(tmp_ctx,
9609                                                get_session_info_system(),
9610                                                p->msg_ctx,
9611                                                &b);
9612         if (!W_ERROR_IS_OK(result)) {
9613                 goto done;
9614         }
9615
9616         result = winreg_get_printer(tmp_ctx, b,
9617                                     lp_servicename(talloc_tos(), snum),
9618                                     &pinfo2);
9619         if (!W_ERROR_IS_OK(result)) {
9620                 goto done;
9621         }
9622
9623         /* check for OID in valuename */
9624
9625         oid_string = strchr(r->in.value_name, ',');
9626         if (oid_string) {
9627                 *oid_string = '\0';
9628                 oid_string++;
9629         }
9630
9631         /* save the registry data */
9632
9633         result = winreg_set_printer_dataex(tmp_ctx, b,
9634                                            pinfo2->sharename,
9635                                            r->in.key_name,
9636                                            r->in.value_name,
9637                                            r->in.type,
9638                                            r->in.data,
9639                                            r->in.offered);
9640
9641         if (W_ERROR_IS_OK(result)) {
9642                 /* save the OID if one was specified */
9643                 if (oid_string) {
9644                         char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9645                                 r->in.key_name, SPOOL_OID_KEY);
9646                         if (!str) {
9647                                 result = WERR_NOMEM;
9648                                 goto done;
9649                         }
9650
9651                         /*
9652                          * I'm not checking the status here on purpose.  Don't know
9653                          * if this is right, but I'm returning the status from the
9654                          * previous set_printer_dataex() call.  I have no idea if
9655                          * this is right.    --jerry
9656                          */
9657                         winreg_set_printer_dataex(tmp_ctx, b,
9658                                                   pinfo2->sharename,
9659                                                   str,
9660                                                   r->in.value_name,
9661                                                   REG_SZ,
9662                                                   (uint8_t *) oid_string,
9663                                                   strlen(oid_string) + 1);
9664                 }
9665
9666                 result = winreg_printer_update_changeid(tmp_ctx, b,
9667                                                         lp_const_servicename(snum));
9668
9669         }
9670
9671 done:
9672         talloc_free(tmp_ctx);
9673         return result;
9674 }
9675
9676 /****************************************************************
9677  _spoolss_DeletePrinterDataEx
9678 ****************************************************************/
9679
9680 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9681                                     struct spoolss_DeletePrinterDataEx *r)
9682 {
9683         const char *printer;
9684         int             snum=0;
9685         WERROR          status = WERR_OK;
9686         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9687
9688         DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9689
9690         if (!Printer) {
9691                 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9692                         "Invalid handle (%s:%u:%u).\n",
9693                         OUR_HANDLE(r->in.handle)));
9694                 return WERR_BADFID;
9695         }
9696
9697         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9698                 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9699                         "printer properties change denied by handle\n"));
9700                 return WERR_ACCESS_DENIED;
9701         }
9702
9703         if (!r->in.value_name || !r->in.key_name) {
9704                 return WERR_NOMEM;
9705         }
9706
9707         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9708                 return WERR_BADFID;
9709         }
9710         printer = lp_const_servicename(snum);
9711
9712         status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9713                                               get_session_info_system(),
9714                                               p->msg_ctx,
9715                                               printer,
9716                                               r->in.key_name,
9717                                               r->in.value_name);
9718         if (W_ERROR_IS_OK(status)) {
9719                 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9720                                                         get_session_info_system(),
9721                                                         p->msg_ctx,
9722                                                         printer);
9723         }
9724
9725         return status;
9726 }
9727
9728 /****************************************************************
9729  _spoolss_EnumPrinterKey
9730 ****************************************************************/
9731
9732 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9733                                struct spoolss_EnumPrinterKey *r)
9734 {
9735         uint32_t        num_keys;
9736         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9737         int             snum = 0;
9738         WERROR          result = WERR_BADFILE;
9739         const char **array = NULL;
9740         DATA_BLOB blob;
9741
9742         DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9743
9744         if (!Printer) {
9745                 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9746                         OUR_HANDLE(r->in.handle)));
9747                 return WERR_BADFID;
9748         }
9749
9750         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9751                 return WERR_BADFID;
9752         }
9753
9754         result = winreg_enum_printer_key_internal(p->mem_ctx,
9755                                          get_session_info_system(),
9756                                          p->msg_ctx,
9757                                          lp_const_servicename(snum),
9758                                          r->in.key_name,
9759                                          &num_keys,
9760                                          &array);
9761         if (!W_ERROR_IS_OK(result)) {
9762                 goto done;
9763         }
9764
9765         if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9766                 result = WERR_NOMEM;
9767                 goto done;
9768         }
9769
9770         *r->out._ndr_size = r->in.offered / 2;
9771         *r->out.needed = blob.length;
9772
9773         if (r->in.offered < *r->out.needed) {
9774                 result = WERR_MORE_DATA;
9775         } else {
9776                 result = WERR_OK;
9777                 r->out.key_buffer->string_array = array;
9778         }
9779
9780  done:
9781         if (!W_ERROR_IS_OK(result)) {
9782                 TALLOC_FREE(array);
9783                 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9784                         *r->out.needed = 0;
9785                 }
9786         }
9787
9788         return result;
9789 }
9790
9791 /****************************************************************
9792  _spoolss_DeletePrinterKey
9793 ****************************************************************/
9794
9795 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9796                                  struct spoolss_DeletePrinterKey *r)
9797 {
9798         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9799         int                     snum=0;
9800         WERROR                  status;
9801         const char *printer;
9802         struct dcerpc_binding_handle *b;
9803         TALLOC_CTX *tmp_ctx;
9804
9805         DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9806
9807         if (!Printer) {
9808                 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9809                         OUR_HANDLE(r->in.handle)));
9810                 return WERR_BADFID;
9811         }
9812
9813         /* if keyname == NULL, return error */
9814         if ( !r->in.key_name )
9815                 return WERR_INVALID_PARAM;
9816
9817         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9818                 return WERR_BADFID;
9819         }
9820
9821         if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9822                 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9823                         "printer properties change denied by handle\n"));
9824                 return WERR_ACCESS_DENIED;
9825         }
9826
9827         printer = lp_const_servicename(snum);
9828
9829         tmp_ctx = talloc_new(p->mem_ctx);
9830         if (!tmp_ctx) {
9831                 return WERR_NOMEM;
9832         }
9833
9834         status = winreg_printer_binding_handle(tmp_ctx,
9835                                                get_session_info_system(),
9836                                                p->msg_ctx,
9837                                                &b);
9838         if (!W_ERROR_IS_OK(status)) {
9839                 goto done;
9840         }
9841
9842         /* delete the key and all subkeys */
9843         status = winreg_delete_printer_key(tmp_ctx, b,
9844                                            printer,
9845                                            r->in.key_name);
9846         if (W_ERROR_IS_OK(status)) {
9847                 status = winreg_printer_update_changeid(tmp_ctx, b,
9848                                                         printer);
9849         }
9850
9851 done:
9852         talloc_free(tmp_ctx);
9853         return status;
9854 }
9855
9856 /****************************************************************
9857  _spoolss_EnumPrinterDataEx
9858 ****************************************************************/
9859
9860 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9861                                   struct spoolss_EnumPrinterDataEx *r)
9862 {
9863         uint32_t        count = 0;
9864         struct spoolss_PrinterEnumValues *info = NULL;
9865         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9866         int             snum;
9867         WERROR          result;
9868
9869         DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9870
9871         *r->out.count = 0;
9872         *r->out.needed = 0;
9873         *r->out.info = NULL;
9874
9875         if (!Printer) {
9876                 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9877                         OUR_HANDLE(r->in.handle)));
9878                 return WERR_BADFID;
9879         }
9880
9881         /*
9882          * first check for a keyname of NULL or "".  Win2k seems to send
9883          * this a lot and we should send back WERR_INVALID_PARAM
9884          * no need to spend time looking up the printer in this case.
9885          * --jerry
9886          */
9887
9888         if (!strlen(r->in.key_name)) {
9889                 result = WERR_INVALID_PARAM;
9890                 goto done;
9891         }
9892
9893         if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9894                 return WERR_BADFID;
9895         }
9896
9897         /* now look for a match on the key name */
9898         result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9899                                             get_session_info_system(),
9900                                             p->msg_ctx,
9901                                             lp_const_servicename(snum),
9902                                             r->in.key_name,
9903                                             &count,
9904                                             &info);
9905         if (!W_ERROR_IS_OK(result)) {
9906                 goto done;
9907         }
9908
9909 #if 0 /* FIXME - gd */
9910         /* housekeeping information in the reply */
9911
9912         /* Fix from Martin Zielinski <mz@seh.de> - ensure
9913          * the hand marshalled container size is a multiple
9914          * of 4 bytes for RPC alignment.
9915          */
9916
9917         if (needed % 4) {
9918                 needed += 4-(needed % 4);
9919         }
9920 #endif
9921         *r->out.count   = count;
9922         *r->out.info    = info;
9923
9924  done:
9925         if (!W_ERROR_IS_OK(result)) {
9926                 return result;
9927         }
9928
9929         *r->out.needed  = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9930                                                spoolss_EnumPrinterDataEx,
9931                                                *r->out.info,
9932                                                *r->out.count);
9933         *r->out.info    = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9934         *r->out.count   = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9935
9936         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9937 }
9938
9939 /****************************************************************************
9940 ****************************************************************************/
9941
9942 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9943                                                  const char *servername,
9944                                                  const char *environment,
9945                                                  struct spoolss_PrintProcessorDirectoryInfo1 *r)
9946 {
9947         WERROR werr;
9948         char *path = NULL;
9949
9950         werr = compose_spoolss_server_path(mem_ctx,
9951                                            servername,
9952                                            environment,
9953                                            SPOOLSS_PRTPROCS_PATH,
9954                                            &path);
9955         if (!W_ERROR_IS_OK(werr)) {
9956                 return werr;
9957         }
9958
9959         DEBUG(4,("print processor directory: [%s]\n", path));
9960
9961         r->directory_name = path;
9962
9963         return WERR_OK;
9964 }
9965
9966 /****************************************************************
9967  _spoolss_GetPrintProcessorDirectory
9968 ****************************************************************/
9969
9970 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9971                                            struct spoolss_GetPrintProcessorDirectory *r)
9972 {
9973         WERROR result;
9974         char *prnproc_share = NULL;
9975         bool prnproc_share_exists = false;
9976         int snum;
9977
9978         /* that's an [in out] buffer */
9979
9980         if (!r->in.buffer && (r->in.offered != 0)) {
9981                 return WERR_INVALID_PARAM;
9982         }
9983
9984         DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9985                 r->in.level));
9986
9987         *r->out.needed = 0;
9988
9989         /* r->in.level is ignored */
9990
9991         /* We always should reply with a local print processor directory so that
9992          * users are not forced to have a [prnproc$] share on the Samba spoolss
9993          * server, if users decide to do so, lets announce it though - Guenther */
9994
9995         snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9996         if (!prnproc_share) {
9997                 return WERR_NOMEM;
9998         }
9999         if (snum != -1) {
10000                 prnproc_share_exists = true;
10001         }
10002
10003         result = getprintprocessordirectory_level_1(p->mem_ctx,
10004                                                     prnproc_share_exists ? r->in.server : NULL,
10005                                                     r->in.environment,
10006                                                     &r->out.info->info1);
10007         if (!W_ERROR_IS_OK(result)) {
10008                 TALLOC_FREE(r->out.info);
10009                 return result;
10010         }
10011
10012         *r->out.needed  = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10013                                                                                    r->out.info, r->in.level);
10014         r->out.info     = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10015
10016         return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10017 }
10018
10019 /*******************************************************************
10020  ********************************************************************/
10021
10022 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10023                                const char *dllname)
10024 {
10025         enum ndr_err_code ndr_err;
10026         struct spoolss_MonitorUi ui;
10027
10028         ui.dll_name = dllname;
10029
10030         ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10031                        (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10032         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10033                 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10034         }
10035         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10036 }
10037
10038 /*******************************************************************
10039  Streams the monitor UI DLL name in UNICODE
10040 *******************************************************************/
10041
10042 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10043                                struct security_token *token, DATA_BLOB *in,
10044                                DATA_BLOB *out, uint32_t *needed)
10045 {
10046         const char *dllname = "tcpmonui.dll";
10047
10048         *needed = (strlen(dllname)+1) * 2;
10049
10050         if (out->length < *needed) {
10051                 return WERR_INSUFFICIENT_BUFFER;
10052         }
10053
10054         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10055                 return WERR_NOMEM;
10056         }
10057
10058         return WERR_OK;
10059 }
10060
10061 /*******************************************************************
10062  ********************************************************************/
10063
10064 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10065                              struct spoolss_PortData1 *port1,
10066                              const DATA_BLOB *buf)
10067 {
10068         enum ndr_err_code ndr_err;
10069         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10070                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10071         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10072                 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10073         }
10074         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10075 }
10076
10077 /*******************************************************************
10078  ********************************************************************/
10079
10080 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10081                              struct spoolss_PortData2 *port2,
10082                              const DATA_BLOB *buf)
10083 {
10084         enum ndr_err_code ndr_err;
10085         ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10086                        (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10087         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10088                 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10089         }
10090         return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10091 }
10092
10093 /*******************************************************************
10094  Create a new TCP/IP port
10095 *******************************************************************/
10096
10097 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10098                              struct security_token *token, DATA_BLOB *in,
10099                              DATA_BLOB *out, uint32_t *needed)
10100 {
10101         struct spoolss_PortData1 port1;
10102         struct spoolss_PortData2 port2;
10103         char *device_uri = NULL;
10104         uint32_t version;
10105
10106         const char *portname;
10107         const char *hostaddress;
10108         const char *queue;
10109         uint32_t port_number;
10110         uint32_t protocol;
10111
10112         /* peek for spoolss_PortData version */
10113
10114         if (!in || (in->length < (128 + 4))) {
10115                 return WERR_GENERAL_FAILURE;
10116         }
10117
10118         version = IVAL(in->data, 128);
10119
10120         switch (version) {
10121                 case 1:
10122                         ZERO_STRUCT(port1);
10123
10124                         if (!pull_port_data_1(mem_ctx, &port1, in)) {
10125                                 return WERR_NOMEM;
10126                         }
10127
10128                         portname        = port1.portname;
10129                         hostaddress     = port1.hostaddress;
10130                         queue           = port1.queue;
10131                         protocol        = port1.protocol;
10132                         port_number     = port1.port_number;
10133
10134                         break;
10135                 case 2:
10136                         ZERO_STRUCT(port2);
10137
10138                         if (!pull_port_data_2(mem_ctx, &port2, in)) {
10139                                 return WERR_NOMEM;
10140                         }
10141
10142                         portname        = port2.portname;
10143                         hostaddress     = port2.hostaddress;
10144                         queue           = port2.queue;
10145                         protocol        = port2.protocol;
10146                         port_number     = port2.port_number;
10147
10148                         break;
10149                 default:
10150                         DEBUG(1,("xcvtcp_addport: "
10151                                 "unknown version of port_data: %d\n", version));
10152                         return WERR_UNKNOWN_PORT;
10153         }
10154
10155         /* create the device URI and call the add_port_hook() */
10156
10157         switch (protocol) {
10158         case PROTOCOL_RAWTCP_TYPE:
10159                 device_uri = talloc_asprintf(mem_ctx,
10160                                 "socket://%s:%d/", hostaddress,
10161                                 port_number);
10162                 break;
10163
10164         case PROTOCOL_LPR_TYPE:
10165                 device_uri = talloc_asprintf(mem_ctx,
10166                         "lpr://%s/%s", hostaddress, queue );
10167                 break;
10168
10169         default:
10170                 return WERR_UNKNOWN_PORT;
10171         }
10172
10173         if (!device_uri) {
10174                 return WERR_NOMEM;
10175         }
10176
10177         return add_port_hook(mem_ctx, token, portname, device_uri);
10178 }
10179
10180 /*******************************************************************
10181 *******************************************************************/
10182
10183 struct xcv_api_table xcvtcp_cmds[] = {
10184         { "MonitorUI",  xcvtcp_monitorui },
10185         { "AddPort",    xcvtcp_addport},
10186         { NULL,         NULL }
10187 };
10188
10189 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10190                                      struct security_token *token, const char *command,
10191                                      DATA_BLOB *inbuf,
10192                                      DATA_BLOB *outbuf,
10193                                      uint32_t *needed )
10194 {
10195         int i;
10196
10197         DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10198
10199         for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10200                 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10201                         return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10202         }
10203
10204         return WERR_BADFUNC;
10205 }
10206
10207 /*******************************************************************
10208 *******************************************************************/
10209 #if 0   /* don't support management using the "Local Port" monitor */
10210
10211 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10212                                  struct security_token *token, DATA_BLOB *in,
10213                                  DATA_BLOB *out, uint32_t *needed)
10214 {
10215         const char *dllname = "localui.dll";
10216
10217         *needed = (strlen(dllname)+1) * 2;
10218
10219         if (out->length < *needed) {
10220                 return WERR_INSUFFICIENT_BUFFER;
10221         }
10222
10223         if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10224                 return WERR_NOMEM;
10225         }
10226
10227         return WERR_OK;
10228 }
10229
10230 /*******************************************************************
10231 *******************************************************************/
10232
10233 struct xcv_api_table xcvlocal_cmds[] = {
10234         { "MonitorUI",  xcvlocal_monitorui },
10235         { NULL,         NULL }
10236 };
10237 #else
10238 struct xcv_api_table xcvlocal_cmds[] = {
10239         { NULL,         NULL }
10240 };
10241 #endif
10242
10243
10244
10245 /*******************************************************************
10246 *******************************************************************/
10247
10248 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10249                                        struct security_token *token, const char *command,
10250                                        DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10251                                        uint32_t *needed)
10252 {
10253         int i;
10254
10255         DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10256
10257         for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10258                 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10259                         return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10260         }
10261         return WERR_BADFUNC;
10262 }
10263
10264 /****************************************************************
10265  _spoolss_XcvData
10266 ****************************************************************/
10267
10268 WERROR _spoolss_XcvData(struct pipes_struct *p,
10269                         struct spoolss_XcvData *r)
10270 {
10271         struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10272         DATA_BLOB out_data = data_blob_null;
10273         WERROR werror;
10274
10275         if (!Printer) {
10276                 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10277                         OUR_HANDLE(r->in.handle)));
10278                 return WERR_BADFID;
10279         }
10280
10281         /* Has to be a handle to the TCP/IP port monitor */
10282
10283         if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10284                 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10285                 return WERR_BADFID;
10286         }
10287
10288         /* requires administrative access to the server */
10289
10290         if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10291                 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10292                 return WERR_ACCESS_DENIED;
10293         }
10294
10295         /* Allocate the outgoing buffer */
10296
10297         if (r->in.out_data_size) {
10298                 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10299                 if (out_data.data == NULL) {
10300                         return WERR_NOMEM;
10301                 }
10302         }
10303
10304         switch ( Printer->printer_type ) {
10305         case SPLHND_PORTMON_TCP:
10306                 werror = process_xcvtcp_command(p->mem_ctx,
10307                                                 p->session_info->security_token,
10308                                                 r->in.function_name,
10309                                                 &r->in.in_data, &out_data,
10310                                                 r->out.needed);
10311                 break;
10312         case SPLHND_PORTMON_LOCAL:
10313                 werror = process_xcvlocal_command(p->mem_ctx,
10314                                                   p->session_info->security_token,
10315                                                   r->in.function_name,
10316                                                   &r->in.in_data, &out_data,
10317                                                   r->out.needed);
10318                 break;
10319         default:
10320                 werror = WERR_INVALID_PRINT_MONITOR;
10321         }
10322
10323         if (!W_ERROR_IS_OK(werror)) {
10324                 return werror;
10325         }
10326
10327         *r->out.status_code = 0;
10328
10329         if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10330                 memcpy(r->out.out_data, out_data.data,
10331                         MIN(r->in.out_data_size, out_data.length));
10332         }
10333
10334         return WERR_OK;
10335 }
10336
10337 /****************************************************************
10338  _spoolss_AddPrintProcessor
10339 ****************************************************************/
10340
10341 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10342                                   struct spoolss_AddPrintProcessor *r)
10343 {
10344         /* for now, just indicate success and ignore the add.  We'll
10345            automatically set the winprint processor for printer
10346            entries later.  Used to debug the LexMark Optra S 1855 PCL
10347            driver --jerry */
10348
10349         return WERR_OK;
10350 }
10351
10352 /****************************************************************
10353  _spoolss_AddPort
10354 ****************************************************************/
10355
10356 WERROR _spoolss_AddPort(struct pipes_struct *p,
10357                         struct spoolss_AddPort *r)
10358 {
10359         /* do what w2k3 does */
10360
10361         return WERR_NOT_SUPPORTED;
10362 }
10363
10364 /****************************************************************
10365  _spoolss_GetPrinterDriver
10366 ****************************************************************/
10367
10368 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10369                                  struct spoolss_GetPrinterDriver *r)
10370 {
10371         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10372         return WERR_NOT_SUPPORTED;
10373 }
10374
10375 /****************************************************************
10376  _spoolss_ReadPrinter
10377 ****************************************************************/
10378
10379 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10380                             struct spoolss_ReadPrinter *r)
10381 {
10382         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10383         return WERR_NOT_SUPPORTED;
10384 }
10385
10386 /****************************************************************
10387  _spoolss_WaitForPrinterChange
10388 ****************************************************************/
10389
10390 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10391                                      struct spoolss_WaitForPrinterChange *r)
10392 {
10393         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10394         return WERR_NOT_SUPPORTED;
10395 }
10396
10397 /****************************************************************
10398  _spoolss_ConfigurePort
10399 ****************************************************************/
10400
10401 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10402                               struct spoolss_ConfigurePort *r)
10403 {
10404         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10405         return WERR_NOT_SUPPORTED;
10406 }
10407
10408 /****************************************************************
10409  _spoolss_DeletePort
10410 ****************************************************************/
10411
10412 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10413                            struct spoolss_DeletePort *r)
10414 {
10415         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10416         return WERR_NOT_SUPPORTED;
10417 }
10418
10419 /****************************************************************
10420  _spoolss_CreatePrinterIC
10421 ****************************************************************/
10422
10423 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10424                                 struct spoolss_CreatePrinterIC *r)
10425 {
10426         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10427         return WERR_NOT_SUPPORTED;
10428 }
10429
10430 /****************************************************************
10431  _spoolss_PlayGDIScriptOnPrinterIC
10432 ****************************************************************/
10433
10434 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10435                                          struct spoolss_PlayGDIScriptOnPrinterIC *r)
10436 {
10437         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10438         return WERR_NOT_SUPPORTED;
10439 }
10440
10441 /****************************************************************
10442  _spoolss_DeletePrinterIC
10443 ****************************************************************/
10444
10445 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10446                                 struct spoolss_DeletePrinterIC *r)
10447 {
10448         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10449         return WERR_NOT_SUPPORTED;
10450 }
10451
10452 /****************************************************************
10453  _spoolss_AddPrinterConnection
10454 ****************************************************************/
10455
10456 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10457                                      struct spoolss_AddPrinterConnection *r)
10458 {
10459         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10460         return WERR_NOT_SUPPORTED;
10461 }
10462
10463 /****************************************************************
10464  _spoolss_DeletePrinterConnection
10465 ****************************************************************/
10466
10467 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10468                                         struct spoolss_DeletePrinterConnection *r)
10469 {
10470         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10471         return WERR_NOT_SUPPORTED;
10472 }
10473
10474 /****************************************************************
10475  _spoolss_PrinterMessageBox
10476 ****************************************************************/
10477
10478 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10479                                   struct spoolss_PrinterMessageBox *r)
10480 {
10481         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10482         return WERR_NOT_SUPPORTED;
10483 }
10484
10485 /****************************************************************
10486  _spoolss_AddMonitor
10487 ****************************************************************/
10488
10489 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10490                            struct spoolss_AddMonitor *r)
10491 {
10492         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10493         return WERR_NOT_SUPPORTED;
10494 }
10495
10496 /****************************************************************
10497  _spoolss_DeleteMonitor
10498 ****************************************************************/
10499
10500 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10501                               struct spoolss_DeleteMonitor *r)
10502 {
10503         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10504         return WERR_NOT_SUPPORTED;
10505 }
10506
10507 /****************************************************************
10508  _spoolss_DeletePrintProcessor
10509 ****************************************************************/
10510
10511 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10512                                      struct spoolss_DeletePrintProcessor *r)
10513 {
10514         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10515         return WERR_NOT_SUPPORTED;
10516 }
10517
10518 /****************************************************************
10519  _spoolss_AddPrintProvidor
10520 ****************************************************************/
10521
10522 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10523                                  struct spoolss_AddPrintProvidor *r)
10524 {
10525         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10526         return WERR_NOT_SUPPORTED;
10527 }
10528
10529 /****************************************************************
10530  _spoolss_DeletePrintProvidor
10531 ****************************************************************/
10532
10533 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10534                                     struct spoolss_DeletePrintProvidor *r)
10535 {
10536         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10537         return WERR_NOT_SUPPORTED;
10538 }
10539
10540 /****************************************************************
10541  _spoolss_FindFirstPrinterChangeNotification
10542 ****************************************************************/
10543
10544 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10545                                                    struct spoolss_FindFirstPrinterChangeNotification *r)
10546 {
10547         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10548         return WERR_NOT_SUPPORTED;
10549 }
10550
10551 /****************************************************************
10552  _spoolss_FindNextPrinterChangeNotification
10553 ****************************************************************/
10554
10555 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10556                                                   struct spoolss_FindNextPrinterChangeNotification *r)
10557 {
10558         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10559         return WERR_NOT_SUPPORTED;
10560 }
10561
10562 /****************************************************************
10563  _spoolss_RouterFindFirstPrinterChangeNotificationOld
10564 ****************************************************************/
10565
10566 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10567                                                             struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10568 {
10569         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10570         return WERR_NOT_SUPPORTED;
10571 }
10572
10573 /****************************************************************
10574  _spoolss_ReplyOpenPrinter
10575 ****************************************************************/
10576
10577 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10578                                  struct spoolss_ReplyOpenPrinter *r)
10579 {
10580         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10581         return WERR_NOT_SUPPORTED;
10582 }
10583
10584 /****************************************************************
10585  _spoolss_RouterReplyPrinter
10586 ****************************************************************/
10587
10588 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10589                                    struct spoolss_RouterReplyPrinter *r)
10590 {
10591         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10592         return WERR_NOT_SUPPORTED;
10593 }
10594
10595 /****************************************************************
10596  _spoolss_ReplyClosePrinter
10597 ****************************************************************/
10598
10599 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10600                                   struct spoolss_ReplyClosePrinter *r)
10601 {
10602         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10603         return WERR_NOT_SUPPORTED;
10604 }
10605
10606 /****************************************************************
10607  _spoolss_AddPortEx
10608 ****************************************************************/
10609
10610 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10611                           struct spoolss_AddPortEx *r)
10612 {
10613         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10614         return WERR_NOT_SUPPORTED;
10615 }
10616
10617 /****************************************************************
10618  _spoolss_RouterFindFirstPrinterChangeNotification
10619 ****************************************************************/
10620
10621 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10622                                                          struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10623 {
10624         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10625         return WERR_NOT_SUPPORTED;
10626 }
10627
10628 /****************************************************************
10629  _spoolss_SpoolerInit
10630 ****************************************************************/
10631
10632 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10633                             struct spoolss_SpoolerInit *r)
10634 {
10635         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10636         return WERR_NOT_SUPPORTED;
10637 }
10638
10639 /****************************************************************
10640  _spoolss_ResetPrinterEx
10641 ****************************************************************/
10642
10643 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10644                                struct spoolss_ResetPrinterEx *r)
10645 {
10646         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10647         return WERR_NOT_SUPPORTED;
10648 }
10649
10650 /****************************************************************
10651  _spoolss_RouterReplyPrinterEx
10652 ****************************************************************/
10653
10654 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10655                                      struct spoolss_RouterReplyPrinterEx *r)
10656 {
10657         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10658         return WERR_NOT_SUPPORTED;
10659 }
10660
10661 /****************************************************************
10662  _spoolss_44
10663 ****************************************************************/
10664
10665 WERROR _spoolss_44(struct pipes_struct *p,
10666                    struct spoolss_44 *r)
10667 {
10668         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10669         return WERR_NOT_SUPPORTED;
10670 }
10671
10672 /****************************************************************
10673  _spoolss_SetPort
10674 ****************************************************************/
10675
10676 WERROR _spoolss_SetPort(struct pipes_struct *p,
10677                         struct spoolss_SetPort *r)
10678 {
10679         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10680         return WERR_NOT_SUPPORTED;
10681 }
10682
10683 /****************************************************************
10684  _spoolss_4a
10685 ****************************************************************/
10686
10687 WERROR _spoolss_4a(struct pipes_struct *p,
10688                    struct spoolss_4a *r)
10689 {
10690         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10691         return WERR_NOT_SUPPORTED;
10692 }
10693
10694 /****************************************************************
10695  _spoolss_4b
10696 ****************************************************************/
10697
10698 WERROR _spoolss_4b(struct pipes_struct *p,
10699                    struct spoolss_4b *r)
10700 {
10701         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10702         return WERR_NOT_SUPPORTED;
10703 }
10704
10705 /****************************************************************
10706  _spoolss_4c
10707 ****************************************************************/
10708
10709 WERROR _spoolss_4c(struct pipes_struct *p,
10710                    struct spoolss_4c *r)
10711 {
10712         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10713         return WERR_NOT_SUPPORTED;
10714 }
10715
10716 /****************************************************************
10717  _spoolss_53
10718 ****************************************************************/
10719
10720 WERROR _spoolss_53(struct pipes_struct *p,
10721                    struct spoolss_53 *r)
10722 {
10723         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10724         return WERR_NOT_SUPPORTED;
10725 }
10726
10727 /****************************************************************
10728  _spoolss_AddPerMachineConnection
10729 ****************************************************************/
10730
10731 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10732                                         struct spoolss_AddPerMachineConnection *r)
10733 {
10734         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10735         return WERR_NOT_SUPPORTED;
10736 }
10737
10738 /****************************************************************
10739  _spoolss_DeletePerMachineConnection
10740 ****************************************************************/
10741
10742 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10743                                            struct spoolss_DeletePerMachineConnection *r)
10744 {
10745         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10746         return WERR_NOT_SUPPORTED;
10747 }
10748
10749 /****************************************************************
10750  _spoolss_EnumPerMachineConnections
10751 ****************************************************************/
10752
10753 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10754                                           struct spoolss_EnumPerMachineConnections *r)
10755 {
10756         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10757         return WERR_NOT_SUPPORTED;
10758 }
10759
10760 /****************************************************************
10761  _spoolss_5a
10762 ****************************************************************/
10763
10764 WERROR _spoolss_5a(struct pipes_struct *p,
10765                    struct spoolss_5a *r)
10766 {
10767         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10768         return WERR_NOT_SUPPORTED;
10769 }
10770
10771 /****************************************************************
10772  _spoolss_5b
10773 ****************************************************************/
10774
10775 WERROR _spoolss_5b(struct pipes_struct *p,
10776                    struct spoolss_5b *r)
10777 {
10778         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10779         return WERR_NOT_SUPPORTED;
10780 }
10781
10782 /****************************************************************
10783  _spoolss_5c
10784 ****************************************************************/
10785
10786 WERROR _spoolss_5c(struct pipes_struct *p,
10787                    struct spoolss_5c *r)
10788 {
10789         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10790         return WERR_NOT_SUPPORTED;
10791 }
10792
10793 /****************************************************************
10794  _spoolss_5d
10795 ****************************************************************/
10796
10797 WERROR _spoolss_5d(struct pipes_struct *p,
10798                    struct spoolss_5d *r)
10799 {
10800         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10801         return WERR_NOT_SUPPORTED;
10802 }
10803
10804 /****************************************************************
10805  _spoolss_5e
10806 ****************************************************************/
10807
10808 WERROR _spoolss_5e(struct pipes_struct *p,
10809                    struct spoolss_5e *r)
10810 {
10811         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10812         return WERR_NOT_SUPPORTED;
10813 }
10814
10815 /****************************************************************
10816  _spoolss_5f
10817 ****************************************************************/
10818
10819 WERROR _spoolss_5f(struct pipes_struct *p,
10820                    struct spoolss_5f *r)
10821 {
10822         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10823         return WERR_NOT_SUPPORTED;
10824 }
10825
10826 /****************************************************************
10827  _spoolss_60
10828 ****************************************************************/
10829
10830 WERROR _spoolss_60(struct pipes_struct *p,
10831                    struct spoolss_60 *r)
10832 {
10833         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10834         return WERR_NOT_SUPPORTED;
10835 }
10836
10837 /****************************************************************
10838  _spoolss_61
10839 ****************************************************************/
10840
10841 WERROR _spoolss_61(struct pipes_struct *p,
10842                    struct spoolss_61 *r)
10843 {
10844         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10845         return WERR_NOT_SUPPORTED;
10846 }
10847
10848 /****************************************************************
10849  _spoolss_62
10850 ****************************************************************/
10851
10852 WERROR _spoolss_62(struct pipes_struct *p,
10853                    struct spoolss_62 *r)
10854 {
10855         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10856         return WERR_NOT_SUPPORTED;
10857 }
10858
10859 /****************************************************************
10860  _spoolss_63
10861 ****************************************************************/
10862
10863 WERROR _spoolss_63(struct pipes_struct *p,
10864                    struct spoolss_63 *r)
10865 {
10866         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10867         return WERR_NOT_SUPPORTED;
10868 }
10869
10870 /****************************************************************
10871  _spoolss_64
10872 ****************************************************************/
10873
10874 WERROR _spoolss_64(struct pipes_struct *p,
10875                    struct spoolss_64 *r)
10876 {
10877         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10878         return WERR_NOT_SUPPORTED;
10879 }
10880
10881 /****************************************************************
10882  _spoolss_65
10883 ****************************************************************/
10884
10885 WERROR _spoolss_65(struct pipes_struct *p,
10886                    struct spoolss_65 *r)
10887 {
10888         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10889         return WERR_NOT_SUPPORTED;
10890 }
10891
10892 /****************************************************************
10893  _spoolss_GetCorePrinterDrivers
10894 ****************************************************************/
10895
10896 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10897                                       struct spoolss_GetCorePrinterDrivers *r)
10898 {
10899         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10900         return WERR_NOT_SUPPORTED;
10901 }
10902
10903 /****************************************************************
10904  _spoolss_67
10905 ****************************************************************/
10906
10907 WERROR _spoolss_67(struct pipes_struct *p,
10908                    struct spoolss_67 *r)
10909 {
10910         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10911         return WERR_NOT_SUPPORTED;
10912 }
10913
10914 /****************************************************************
10915  _spoolss_GetPrinterDriverPackagePath
10916 ****************************************************************/
10917
10918 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10919                                             struct spoolss_GetPrinterDriverPackagePath *r)
10920 {
10921         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10922         return WERR_NOT_SUPPORTED;
10923 }
10924
10925 /****************************************************************
10926  _spoolss_69
10927 ****************************************************************/
10928
10929 WERROR _spoolss_69(struct pipes_struct *p,
10930                    struct spoolss_69 *r)
10931 {
10932         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10933         return WERR_NOT_SUPPORTED;
10934 }
10935
10936 /****************************************************************
10937  _spoolss_6a
10938 ****************************************************************/
10939
10940 WERROR _spoolss_6a(struct pipes_struct *p,
10941                    struct spoolss_6a *r)
10942 {
10943         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10944         return WERR_NOT_SUPPORTED;
10945 }
10946
10947 /****************************************************************
10948  _spoolss_6b
10949 ****************************************************************/
10950
10951 WERROR _spoolss_6b(struct pipes_struct *p,
10952                    struct spoolss_6b *r)
10953 {
10954         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10955         return WERR_NOT_SUPPORTED;
10956 }
10957
10958 /****************************************************************
10959  _spoolss_6c
10960 ****************************************************************/
10961
10962 WERROR _spoolss_6c(struct pipes_struct *p,
10963                    struct spoolss_6c *r)
10964 {
10965         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10966         return WERR_NOT_SUPPORTED;
10967 }
10968
10969 /****************************************************************
10970  _spoolss_6d
10971 ****************************************************************/
10972
10973 WERROR _spoolss_6d(struct pipes_struct *p,
10974                    struct spoolss_6d *r)
10975 {
10976         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10977         return WERR_NOT_SUPPORTED;
10978 }
10979
10980 /****************************************************************
10981  _spoolss_RpcGetJobNamedPropertyValue
10982 ****************************************************************/
10983
10984 WERROR _spoolss_RpcGetJobNamedPropertyValue(struct pipes_struct *p,
10985                                             struct spoolss_RpcGetJobNamedPropertyValue *r)
10986 {
10987         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10988         return WERR_NOT_SUPPORTED;
10989 }
10990
10991 /****************************************************************
10992  _spoolss_RpcSetJobNamedProperty
10993 ****************************************************************/
10994
10995 WERROR _spoolss_RpcSetJobNamedProperty(struct pipes_struct *p,
10996                                        struct spoolss_RpcSetJobNamedProperty *r)
10997 {
10998         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10999         return WERR_NOT_SUPPORTED;
11000 }
11001
11002 /****************************************************************
11003  _spoolss_RpcDeleteJobNamedProperty
11004 ****************************************************************/
11005
11006 WERROR _spoolss_RpcDeleteJobNamedProperty(struct pipes_struct *p,
11007                                           struct spoolss_RpcDeleteJobNamedProperty *r)
11008 {
11009         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11010         return WERR_NOT_SUPPORTED;
11011 }
11012
11013 /****************************************************************
11014  _spoolss_RpcEnumJobNamedProperties
11015 ****************************************************************/
11016
11017 WERROR _spoolss_RpcEnumJobNamedProperties(struct pipes_struct *p,
11018                                           struct spoolss_RpcEnumJobNamedProperties *r)
11019 {
11020         p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11021         return WERR_NOT_SUPPORTED;
11022 }